# Python custom list class initialization

Consider the class AB below that is to be used as a simple customized list of A objects for lookup operations.

Can this code be improved to avoid instantiating AB with an empty list [] (i.e., perhaps modify __add__ in some way)?

class A():
def __init__(self, arg):
self.arg = arg

class AB():
def __init__(self, list):
self.list = list

return AB(self.list + [other])

ab = AB([])
ab += A(1)
ab += A(2)


Sure, you can play with the default argument value:

class AB:
def __init__(self, data=None):
self.data = data if data is not None else []

return AB(self.data + [other.arg])


Other notes:

• list is a bad variable name as it is shadowing the built-in list keyword
• remove redundant parentheses after the class name

Demo:

In [1]: ab = AB()

In [2]: ab += A(1)

In [3]: ab += A(2)

In [4]: print(ab.data)
[<__main__.A instance at 0x10afb14d0>, <__main__.A instance at 0x10afa0998>]

• I was looking for other ways to build __add__, but I guess that changing __init__ works too. Thanks for the tips. Note that it is meant for AB(self.data + [other]) (without .arg) in order to maintain a list of A objects. – dfernan Feb 7 '17 at 21:36
• @dfernan ah, gotcha, I'll remove the last suggestion. Thanks. – alecxe Feb 7 '17 at 21:36
• If you just use data=[] directly instead of be None indirection does that reuse a single list between __init__ calls? Otherwise that seems cleaner. – CAD97 Feb 7 '17 at 23:05
• Just got an opportunity to test. Yes, doing data=[] as a default argument leads to the same list being used for all invocations of __init__. However, this is only an issue if you implement __iadd__. – CAD97 Feb 8 '17 at 4:46

I agree that default arguments can (and should) be used for the backing list of your class.

In addition, consider inheriting from collections.abc.Sequence and delegating __getitem__ and __len__ to the backing list. (Add other list-like methods as necessary.) This will make sure your class acts as a well-behaved list-like.

In order to qualify as an Iterable, you must define __iter__ or __getitem__. In order to qualify as a Sequence you must be an Iterable that provides __getitem__ and __len__. It's up to you how much functionality you want to provide, but the Sequence ABC exists for a reason.

My two cents.

class A():
def __init__(self, arg):
self.arg = arg

class AB():
def __init__(self):
pass

if not hasattr(self, '_list'):
setattr(self, '_list', [other])
else:
self._list.append(other)

return self

ab = AB()
ab += A(1)
ab += A(3)

print(ab._list[1].arg) # Prints 3


We completely avoid the creation of the _list parameter, unless we add an A() object.

Note that we are overriding the += operator specifically.