Separate __init__ function of MIMapping

def _MI_init(self, *args, **kw):
    '''
    Separate __init__ function of MIMapping
    '''

    items, names = [], None

    n_args = len(args)

    if n_args >= 1:
        items = args[0]

        if isinstance(items, Mapping):  # copy from dict
            if isinstance(items, MIMapping):
                names = force_list(items.indices.keys())  # names may be overwritten by second arg
            items = force_list(items.items())
        else:  # try to get data from items() or keys() method
            if hasattr(items, 'items'):
                try:
                    items = force_list(items.items())
                except TypeError:  # items() may be not callalbe
                    pass
            else:
                items = cvt_iter(items)

    if n_args >= 2:
        names = args[1] # may be None
        names = cvt_iter(names)

    if n_args >= 3:
        raise TypeError('At most 2 positional arguments allowed (%s given)' % n_args)

    if items:  # check item length
        n_index = len(items[0])
        for item in items[1:]:
            if len(item) != n_index:
                raise ValueError('Length of all items must equal')
    else:
        n_index = 0

    if kw:
        if n_index == 0:
            n_index = 2
        else:
            if n_index != 2:
                raise ValueError('Number of indices must be 2 (got %s) '
                                 'when keyword arguments are used' % n_index)
        items.extend(kw.items())

    if n_index > 0:
        if names is not None:
            if len(names) != n_index:
                raise ValueError('Length of names (%s) does not match '
                                 'length of items (%s)' % (len(names), n_index))

    if names is None:  # generate default names
        names = ['index_%s' % (i+1) for i in range(n_index)] # starts from index_1
    else:
        map(MI_check_index_name, names)

    self.indices = d = IdxOrdDict() # the internal dict
    for index in names:
        if index in d:
            raise ValueError('Duplicate index name: %s in %s' % (index, names))
        d[index] = AttrOrdDict()

    if n_index > 0:
        d[0] = self
        for item in items:
            primary_key = item[0]
            if n_index == 1:
                value = primary_key
            elif n_index == 2:
                value = item[1]
            else:
                value = list(item[1:]) # copy
            # will handle duplicate
            _MI_setitem(self, primary_key, value)