Home > Article > Backend Development > How do you add properties to a class dynamically in Python?
You aim to create a mock class that mimics a database result set. When a database query returns, for instance, {'ab':100, 'cd':200}, you expect to see:
>>> dummy.ab 100
Although adding a property to a class dynamically is feasible, it must be added to the class itself.
>>> class Foo(object): ... pass ... >>> foo = Foo() >>> foo.a = 3 >>> Foo.b = property(lambda self: self.a + 1) >>> foo.b 4
A property is a simple implementation of a descriptor, which is an object that provides custom attribute handling on a particular class. It acts as a substitute for an extensive if tree in __getattribute__.
When you request foo.b, Python recognizes that the b defined on the class follows the descriptor protocol, which simply indicates an object with a get__, __set__, or __delete method. The descriptor assumes responsibility for handling that attribute, prompting Python to call Foo.b.__get__(foo, Foo), and the return value is returned to you as the attribute's value. In property's case, each of these methods simply invokes the fget, fset, or fdel you supplied to the property constructor.
Descriptors are Python's mechanism for exposing the intricacies of its overall OO implementation. Incidentally, there is a distinct type of descriptor that is even more prevalent than property.
>>> class Foo(object): ... def bar(self): ... pass ... >>> Foo().bar <bound method Foo.bar of <__main__.Foo object at 0x7f2a439d5dd0>> >>> Foo().bar.__get__ <method-wrapper '__get__' of instancemethod object at 0x7f2a43a8a5a0>
The humble method is yet another type of descriptor. Its get prefixes the calling instance as the first argument; in essence, it does this:
def __get__(self, instance, owner): return functools.partial(self.function, instance)
This is likely why descriptors only apply to classes: they formalize the mechanisms that underpin classes in the first place. They're the exception to the rule: you can undoubtedly assign descriptors to a class, despite classes themselves being type instances. In fact, attempting to retrieve Foo.bar still invokes property.__get__; however, it is idiomatic for descriptors to return themselves when accessed as class attributes.
Descriptors enable the majority of Python's OO system to be written in Python itself.
The above is the detailed content of How do you add properties to a class dynamically in Python?. For more information, please follow other related articles on the PHP Chinese website!