[Reprinted] Python descriptor introduction, reprinted python character Introduction
Source: Alex Starostin
Link: www.ibm.com/developerworks/cn/opensource/ospythondescriptors/
For Python @ modifier articles, refer to: https://my.oschina.net/shyl/blog/637990,
Introduction
Python 2.2 introduces Python descriptors and some new style classes, but they are not widely used. Python descriptor is a method for creating managed properties. In addition to other advantages, managed properties are also used to protect attributes from being modified or to automatically update the value of a dependency property.
Descriptors increase understanding of Python and improve coding skills. This article introduces the descriptor protocol and demonstrates how to create and use descriptors.
Descriptor Protocol
The Python descriptor protocol is only a method that specifies the event to occur when attributes are referenced in the model. It allows programmers to easily and effectively manage attribute access:
1. set 2, get 3, and delete
In other programming languages, descriptors are called setter and getter, while common functions are used to Get and Set a private variable. Python does not have the concept of private variables, and the descriptor protocol can be used as a Python method to implement functions similar to private variables.
In general, a descriptor is an object property with binding behavior, and its attribute access will be overwritten by methods in the descriptor protocol. These methods are _ get _, _ set _, and _ delete __. If any of these methods defines an object, it is considered a descriptor. Use Listing 1 to learn more about these methods.
Listing 1. descriptor Method
__get__(self, instance, owner)__set__(self, instance, value)__delete__(self, instance)
Where:
_ Get _ is used to access attributes. It returns the attribute value, or an AttributeError error occurs if the Requested attribute does not exist.
_ Set _ will be called in the attribute allocation operation. NO content is returned.
_ Delete _ controls the delete operation. NO content is returned.
Note that the descriptor is assigned to a class instead of an instance. Modifying this class will overwrite or delete the descriptor itself, rather than trigger its code.
Use of descriptors
Consider email attributes. Before assigning a value to this attribute, you must check the mail format. This descriptor allows you to process an email using a regular expression, then validate the format, and assign it to an attribute.
In many other cases, the Python protocol descriptor controls access to attributes, such as protecting the name attribute.
Create Descriptor
You can create a descriptor in many ways:
Create a class and override any descriptor method: __set _, _ get _, and _ delete __. This method is used when a descriptor needs to span multiple different classes and attributes, such as type verification.
The attribute type can be used to create descriptors more easily and flexibly.
The attribute descriptor combines the attribute type method with the Python descriptor.
The following examples are similar in their operations. The difference lies in the implementation method.
Create a descriptor using class methods
class Descriptor(object): def __init__(self): self._name = '' def __get__(self, instance, owner): print "Getting: %s" % self._name return self._name def __set__(self, instance, name): print "Setting: %s" % name self._name = name.title() def __delete__(self, instance): print "Deleting: %s" %self._name del self._name class Person(object): name = Descriptor()
Use the code and view the output:
>>> user = Person()>>> user.name = 'john smith'Setting: john smith>>> user.nameGetting: John Smith'John Smith'>>> del user.nameDeleting: John Smith
The following methods overwrite the _ set _ (), _ get _ (), and _ delete _ () Methods of the parent class to create a descriptor class:
Before the assignment, change the attribute value to the title (the first letter is in upper case, and the other letters are in lower case ). This helps store and output names.
The uppercase conversion can also be moved to the _ get _ () method. _ Value has an initial value and is converted to a title based on the get request.
Create a descriptor using the property type
Although the descriptor defined above is valid and can be used normally, you can also use the attribute type method. By using property (), you can easily create available descriptors for any attribute. The syntax for creating property () is property (fget = None, fset = None, fdel = None, doc = None), where:
Fget: Method for retrieving attributes
Fset: attribute setting method
Fdel: attribute deletion method
Doc: docstring
This example is rewritten using properties, as shown in.
Class Person (object): def _ init _ (self): self. _ name = ''def fget (self): print" Getting: % s "% self. _ name return self. _ name def fset (self, value): print "Setting: % s" % value self. _ name = value. title () def fdel (self): print "Deleting: % s" % self. _ name del self. _ name = property (fget, fset, fdel, "I'm the property. ") use this code and view the output: >>> user = Person () >>> user. name = 'John smith 'Setting: john smith >>> user. nameGetting: John Smith 'John Smith '> del user. nameDeleting: John Smith
Obviously, the results are the same. Note that the fget, fset, and fdel methods are optional. However, if these methods are not specified, an AttributeError error occurs during each operation. For example, when the name attribute is declared, fset is set to None, and then developers try to assign a value to the name attribute. An AttributeError error occurs.
This method can be used to define read-only attributes in the system:
Name = property (fget, None, fdel, "I'm the property") user. name = 'John smith 'output: Traceback (most recent call last): File stdin, line 21, in m has duleuser. name = 'John smith 'AttributeError: can't set attribute
Use attribute modifiers to create Descriptors
You can use the Python modifier to create a descriptor, as shown in. Python modifiers are specific modifications to the Python syntax, allowing you to easily change functions and methods. In this example, the attribute management method is modified. Find more information about the Python modifier in the developerWorks Article Decorators make magic easy.
class Person(object): def __init__(self): self._name = '' @property def name(self): print "Getting: %s" % self._name return self._name @name.setter def name(self, value): print "Setting: %s" % value self._name = value.title() @name.deleter def name(self): print ">Deleting: %s" % self._name del self._name
Create a descriptor at runtime
The name attribute is used in all previous examples. This method has the following limitations: _ set _ (), _ get _ (), and _ delete _ () must be overwritten for each attribute __(). Listing 5 provides a possible solution to help developers add property properties at runtime. This solution uses the attribute type to construct the data descriptor.
Use attribute modifiers to create Descriptors
Class Person (object): def addProperty (self, attribute): # create local setter and getter with a special attribute name getter = lambda self: self. _ getProperty (attribute) setter = lambda self, value: self. _ setProperty (attribute, value) # construct property attribute and add it to the class setattr (self. _ class __, attribute, property (fget = getter, \ fset = setter, \ doc = "Auto-generated method") def _ setProperty (self, attribute, value ): print "Setting: % s = % s" % (attribute, value) setattr (self, '_' + attribute, value. title () def _ getProperty (self, attribute): print "Getting: % s" % attribute return getattr (self, '_' + attribute) let's run this code: >>> user = Person () >>> user. addProperty ('name') >>> user. addProperty ('phone') >>> user. name = 'John smith 'Setting: name = john smith >>> user. phone = '000000' Setting: phone = 12345 >>> user. nameGetting: name 'John Smith '>>> user. _ dict __{ '_ phone': '000000',' _ name': 'John Smith '}
This will create the name and phone attributes at runtime. They can be accessed according to the corresponding name, but according to the definition in the _ setProperty method, they will be stored in the object namespace directory as _ name and _ phone. Basically, name and phone are internal _ name and _ phone access characters.
When developers try to add the name property, you may have questions about the _ name property in the system. In fact, it overwrites the existing _ name attribute with the new property. The Code allows you to control how attributes are processed within a class.