Consider the classAB below that is to be used as a simple customized list ofA objects for lookup operations.
Can this code be improved to avoid instantiatingAB with an empty list[] (i.e., perhaps modify__add__ in some way)?
class A(): def __init__(self, arg): self.arg = argclass AB(): def __init__(self, list): self.list = list def __add__(self, other): return AB(self.list + [other])ab = AB([])ab += A(1)ab += A(2)3 Answers3
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 [] def __add__(self, other): return AB(self.data + [other.arg])Other notes:
listis a bad variable name as it is shadowing the built-inlistkeyword- 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>]- \$\begingroup\$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 forAB(self.data + [other])(without.arg) in order to maintain a list ofAobjects.\$\endgroup\$dfernan– dfernan2017-02-07 21:36:01 +00:00CommentedFeb 7, 2017 at 21:36 - \$\begingroup\$@dfernan ah, gotcha, I'll remove the last suggestion. Thanks.\$\endgroup\$alecxe– alecxe2017-02-07 21:36:43 +00:00CommentedFeb 7, 2017 at 21:36
- \$\begingroup\$If you just use
data=[]directly instead of beNoneindirection does that reuse a single list between__init__calls? Otherwise that seems cleaner.\$\endgroup\$CAD97– CAD972017-02-07 23:05:00 +00:00CommentedFeb 7, 2017 at 23:05 - 1\$\begingroup\$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__.\$\endgroup\$CAD97– CAD972017-02-08 04:46:09 +00:00CommentedFeb 8, 2017 at 4:46
I agree that default arguments can (and should) be used for the backing list of your class.
In addition, consider inheriting fromcollections.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 anIterable, you must define__iter__ or__getitem__. In order to qualify as aSequence 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 = argclass AB(): def __init__(self): pass def __iadd__(self, other): if not hasattr(self, '_list'): setattr(self, '_list', [other]) else: self._list.append(other) return selfab = AB()ab += A(1)ab += A(3)print(ab._list[1].arg) # Prints 3We completely avoid the creation of the_list parameter, unless we add anA() object.
Note that we are overriding the+= operator specifically.
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.


