Possible Duplicate:
When and why might I assign an instance of a descriptor class to a class attribute in Python rather than use a property?
I'm confused as to when to use a property vs a descriptor. I read that a property is a specialized descriptor.
Can someone please post how this works?
The most accessible technique is to use the property function to define get, set and delete methods associated with an attribute name. The property function builds descriptors for you. A slightly less accessible, but more extensible and reusable technique is to define descriptor classes yourself.
Python descriptors are a way to create managed attributes. Among their many advantages, managed attributes are used to protect an attribute from changes or to automatically update the values of a dependant attribute. Descriptors increase an understanding of Python, and improve coding skills.
Descriptors are Python objects that implement a method of the descriptor protocol, which gives you the ability to create objects that have special behavior when they're accessed as attributes of other objects.
Python __get__ Magic Method. Python's __get__() magic method defines the dynamic return value when accessing a specific instance and class attribute. It is defined in the attribute's class and not in the class holding the attribute (= the owner class).
You should read the docs on what descriptors actually are. The Cliff's Notes version: descriptors are a low-level mechanism that lets you hook into an object's attributes being accessed. Properties are a high-level application of this; that is, properties are implemented using descriptors. Or, better yet, properties are descriptors that are already provided for you in the standard library.
If you need a simple way to return a computed value from an attribute read, or to call a function on an attribute write, use the @property
decorator. The descriptor API is more flexible, but less convenient, and arguably "overkill" and non-idiomatic in this situation. It's useful for more advanced use cases, like implementing bound methods, or static and class methods; when you need to know, for example, if the attribute was accessed through the type object, or an instance of the type.
You can read more about both from here. But here's a simple example from the same book that tries to explain the differnce solving what essentialy is the same problem. As you can see, the implementation using properties is much simpler.
There are several ways that we can tap into Python's internal mechanisms for getting and setting attribute values. The most accessible technique is to use the property function to define get, set and delete methods associated with an attribute name. The property function builds descriptors for you. A slightly less accessible, but more extensible and reusable technique is to define descriptor classes yourself. This allows you considerable flexibility. You do this by creating a class which defines get, set and delete methods, and you associate your descriptor class with an attribute name.
The property function gives us a handy way to implement a simple descriptor without defining a separate class. Rather than create a complete class definition, we can write getter and setter method functions, and then bind these functions to an attribute name.
Descriptor example:
class Celsius( object ):
def __init__( self, value=0.0 ):
self.value= float(value)
def __get__( self, instance, owner ):
return self.value
def __set__( self, instance, value ):
self.value= float(value)
class Farenheit( object ):
def __get__( self, instance, owner ):
return instance.celsius * 9 / 5 + 32
def __set__( self, instance, value ):
instance.celsius= (float(value)-32) * 5 / 9
class Temperature( object ):
celsius= Celsius()
farenheit= Farenheit()
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0
Property example:
class Temperature( object ):
def fget( self ):
return self.celsius * 9 / 5 + 32
def fset( self, value ):
self.celsius= (float(value)-32) * 5 / 9
farenheit= property( fget, fset )
def cset( self, value ):
self.cTemp= float(value)
def cget( self ):
return self.cTemp
celsius= property( cget, cset, doc="Celsius temperature" )
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0
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