In Python, I can add an attribute to a class C
which I have previously defined. However, I cannot add an attribute to list
- the resulting error message explains that this is because list
is a built-in type:
>>> class C: pass
...
>>> C.foo = 1
>>> C.foo
1
>>> list.foo = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'list'
Similarly, it is possible to add an attribute to an instance of C
, but not to an instance of list
. In this case, however, the error message is much more vague:
>>> o = C()
>>> o.bar = 2
>>> o.bar
2
>>> o = []
>>> o.bar = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'bar'
Why can't I add members to instances of list
? Is it, again, because list
is a built-in type?
More generally, which objects in Python can have attributes added dynamically?
Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.
We can use hasattr() function to find if a python object obj has a certain attribute or property. hasattr(obj, 'attribute'): The convention in python is that, if the property is likely to be there, simply call it and catch it with a try/except block.
Dynamic attributes represent changing characteristics of the resource. Dynamic attributes of a host resource, for example, would identify such things as the average number of processes that are waiting in the run queue, processor idle time, and the number of users who are currently logged on.
The attributes are data members (class variables and instance variables) and methods, accessed via dot notation. Class variable − A variable that is shared by all instances of a class. Class variables are defined within a class but outside any of the class's methods.
When setting arbitrary properties on an object, this effectively mutates the object’s __dict__
. The __dict__
is a dictionary that stores all members of the object. So in order to add members to an object, there are two conditions:
__dict__
.__dict__
needs to be mutable.There are multiple reasons why one of these conditions may not be true. The following categories of types will usually do not allow object modifications:
int
, str
, list
, bytes
, … probably most (but not all) built-in types
__slots__
. Slots is an explicit way to turn of the __dict__
and replace it by a fixed set of members instead. So obviously, this will prevent later additions to the object (per design).What are good ways to detect whether you can modify an object? Well, check conditions from above. Whether the object has a __dict__
:
>>> class Example:
pass
>>> class SlotsExample:
__slots__ = ['x']
>>> hasattr(Example(), '__dict__')
True
>>> hasattr(SlotsExample(), '__dict__')
False
>>> hasattr(list, '__dict__')
True
>>> hasattr([], '__dict__')
False
And whether the __dict__
is a real dictionary:
>>> isinstance(Example().__dict__, dict)
True
>>> isinstance(list.__dict__, dict)
False
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