Python built-in descriptor python has some built-in descriptor objects, such as PRoperty, staticmethod, and classmethod. python implementation is as follows:
Python built-in descriptor
Python has some built-in descriptor objects, such as PRoperty, staticmethod, and classmethod. python implementation is as follows:
Class Property (object ):
Def _ init _ (self, getf, setf, delf, doc ):
Self. getf = getf
Self. setf = setf
Self. delf = delf
Self.doc = doc
Def _ get _ (self, instance, own = None ):
If instance is None:
Return self
If self. getf is None:
Raise AttributeError
Return self. getf (instance)
Def _ set _ (self, instance, value ):
If self. setf is None:
Raise AttributeError
Self. setf (instance, value)
Def _ del _ (self, instance ):
If self. delf is None:
Raise AttributeError
Self. delf (instance)
Class StaticMethod (object ):
Def _ init _ (self, func ):
Self. func = func
Def _ get _ (self, instance, own = None ):
Return self. func
Class ClassMethod (object ):
Def _ init _ (self, func ):
Self. func = func
Def _ get _ (self, instance, own = None ):
If own is None:
Own = type (instance)
Def callfunc (* args ):
Return self. func (own, * args)
Return callfunc
Set aliases for attribute values
Sometimes you want to use one property name as the alias of another property name. for example, if you want to set the default value of some properties, it must be the same as the current value of other properties, and you also need to set and delete them independently.
Class DefaultAlias (object ):
Def _ init _ (self, name ):
Self. name = name
Def _ get _ (self, instance, own ):
If instance is None: # class attribute access
Return self
Return getattr (instance, self. name). title ()
Class Person (object ):
Def _ init _ (self, name, aliasname = None ):
Self. name = name
If aliasname is not None:
Self. aliasname = aliasname
Aliasname = DefaultAlias ('name ')
>>> P = Person ('Sam ')
>>> P. aliasname
'Sam'
>>> P. aliasname = 'Jack'
>>> P. aliasname
'Jack'
>>> Del p. aliasname
>>> P. aliasname
'Sam'
In this way, an alias aliasname is set for the attribute name, or the aliasname value is stored in the name. DefaultAlias is not a data descriptor because it does not have the _ set _ method, but rather a non-data descriptor. Therefore, when we assign a value to an instance property (p. aliasname = 'Jack'), the instance will normally record the property, and the instance property will overwrite the class property. In this way, the aliasname attribute can be set separately without affecting the name attribute. When we delete del p. aliasname, the attributes of the instance are deleted and the class attributes are displayed again.
For some developed classes, to maintain compatibility with subsequent versions, you can use a new name to name methods and attributes, while retaining the availability of old names.
Class OldAlias (object ):
Def _ init _ (self, name, oldname ):
Self. name = name
Self. oldname = oldname
Def _ warn (self ):
Print 'use % r, not % R' % (self. name, self. oldname)
Def _ get _ (self, instance, own ):
Self. _ warn ()
If instance is None:
Return self
Return getattr (instance, self. name)
Def _ set _ (self, instance, value ):
Self. _ warn ()
Setattr (instance, self. name, value)
Def _ del _ (self, instance ):
Self. _ warn ()
Delattr (instance, self. name)
Class NewClass (object ):
Def _ init _ (self, newname ):
Self. newname = newname
Oldname = OldAlias ('newname', 'oldname ')
>>> C = NewClass ('A ')
>>> C. oldname
Use 'newname', not 'oldname'
'A'
The old code that uses this class uses the class attribute oldname, and a warning message is printed to encourage users to use the new attribute newname.
Cache property value
Calculate the values of instance attributes or class attributes as needed, and provide automatic cache.
Class CachedAttribute (object ):
Def _ init _ (self, method, name = None ):
Self. method = method
Self. name = name if name else method. _ name __
Def _ get _ (self, instance, own ):
If instance is None:
Return self
Result = self. method (instance)
Setattr (instance, self. name, result)
Return result
Class MyObject (object ):
Def _ init _ (self, n ):
Self. n = n
@ CachedAttribute
Def square (self ):
Return self. n * self. n
>>> M = MyObject (2)
>>> M. square
4
>>> M. n = 5
>>> M. square
4
>>> Del m. square
>>> M. square
25
After the first access to m. square, the square attribute is cached in instance m. When the instance attribute n is changed, the square attribute is not changed. If you need to clear the cache, del m. square. The value of accessing the square attribute again will be calculated again.
Cache class attributes:
Class CachedClassAttribute (CachedAttribute ):
Def _ get _ (self, instance, own ):
Return super (CachedClassAttribute, self). _ get _ (own, own)
Class MyClass (object ):
Class_attr = 24
@ CachedClassAttribute
Def square (cls ):
Return cls. class_attr * cls. class_attr
All such instances have the same cache value:
>>> A = MyClass ()
>>> B = MyClass ()
>>> A. square
>>> Print a. square
576
>>> Print B. square
576
>>> Print MyClass. square
576
The above is the content of the python descriptor (2). For more information, see The PHP Chinese website (www.php1.cn )!