In python 3, you can add member variables to a custom object after the class declaration:
class a():
pass
b = a()
b.c = 1 #okay
print(b.c) #outputs 1
However, doing the same for a list object throws an exception:
d = []
d.e = 1 #throws AttributeError: 'list' object has no attribute 'e'
Can someone explain why this is happening?
Not all objects support arbitrary attribute assignment.
Most built-in types don't, including lists, tuples, strings, bytes, dictionaries, sets, booleans, numeric types, etc. On the other hand, function objects do, as do module objects (you are adding new globals to that module when you do).
In other words, just because custom classes and instances support assignment, doesn't mean other types do too. To support arbitrary attributes these types would need to have a __dict__
dictionary per instance, a non-trivial memory cost for very little advantage, especially when a typical Python program creates a lot of instances of these types.
Note that when you use the __slots__
feature to save per-instance memory for custom classes, you cannot assign attributes to those instances either:
>>> class Foo:
... __slots__ = ('spam', 'eggs')
...
>>> foo = Foo()
>>> foo.ham = "won't work"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'ham'
Vice versa, you can subclass the built-in types, at which point the subclass does support arbitrary attribute assignment (as the subclass instances will have a __dict__
attribute):
>>> class FooList(list):
... pass
...
>>> foo_list = FooList()
>>> foo_list.ham = 'This does work'
That is, unless you use __slots__
of course.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With