Reading Learning - Python - Descriptor (python3)

What is the descriptor of the Zhihu article I transferred to ( https://zhuanlan.zhihu.com/p/32487852 ) ?
A descriptor is a class that implements any one of __get__, __set__, and __delete__. is an excellent way to manage data attributes. Before learning descriptors, let's learn about attributes.
1. Properties

在python中,对象的属性和方法都统称为属性。不管是类还是实例它们的属性都是以字典的形式存储在__dict__中。如下:

class A:
attr_a = 1
class B(A):
attr_b = 2
def init(self,c):
self.attr_c = c
"""

a = B(3)
a.attr_a,a.attr_b,a.attr_c
(1,2,3)
a.dict
{'attr_c':3}
B.dict
mappingproxy({'module': 'main', 'attr_b': 2,
'init':

而属性的存储在__dict__里也有一定的“层次感”。类的属性只会存在本类的__dict__中,实例的属性只会存在实例的__dict__中。如上,attr_c在a.__dict__中,attr_b在B.__dict__,而attr_a则在A.__dict__中。

object.getattribute(self,name)
object.setattribute(self,name,value)

General attribute access is to use "." to get attributes, such as a.attr_a. When "." is used, normally python will call __getattribute__ to get attributes and __setattr__ to set attributes.

Python's attribute reading and writing methods are somewhat unequal: when reading attributes on an instance, there is a priority order. It will look for the instance first. If not, it will go to the class or parent class to find it, and it will throw AttributeError before writing attributes. When it is on the class, it will affect the instance. If you write an attribute on the instance, it will only operate on the instance and cannot affect the class.

a.attr_b,a.attr_c
(2,3)
a.attr_b = 4
a.attr_b,B.attr_b
(4,2)
a.dict
{'attr_b':4,'attr_c':3}
A.attr_a = 5
a.attr_a
5
del a.attr_b
a.attr_b,a.dict
(2,{'attr_c':3})

2. Descriptors

So what exactly are descriptors used for? Descriptors are a technique for using the same access method for most properties. A separate descriptor is meaningless, only the descriptor instance is managed in another class (hereinafter collectively referred to as managed class) as a class attribute.

object.get(self,instance,owner)
object.set(self,instance,value)
object.delete(self,instance)

self: descriptor instance

instance: managed class instance

owner: managed class

For example, the value of the descriptor control class attribute is not negative.

class Des:
def init(self,s_name):
self.s_name = s_name
def get(self,instance,owner_):
return instance.dict[self.s_name]
def set(self,instance,value):
if value <= 0:
raise ValueError('value must be > 0')
instance.dict[self.s_name] = value

class One:
x = Des('x')
y = Des('y')
def init(self,x,y,z):
self.x = x
self.y = y
self.z = z
"""

a = One(1,2,3)
a.dict
{'x':1,'y':2,'z':3}
a.x
1
a.x = 0
...
ValueError: value must be > 0
a.x = 3
a.x
3
a.z = 0
a.z
0
"""

Des is a descriptor that controls the properties of the managed class (One). When accessing attributes, python has such a behavior: when accessing attributes, it will first see if it is a descriptor, if so, call __get__ or __set__ to read and write the attribute; if not, call __getattribute__ or __setattr__ to read and write attributes. That is, the descriptor overrides how the properties of the managed class are read and written.

Descriptors have three methods: __get__, __set__ and __delete__. Descriptors with set (and delete ) are data descriptors, and only __get__ descriptors are non-data descriptors. General data descriptors have __get__ and set . There is only a data descriptor for __set__, unless the managed instance has instance attributes, otherwise the managed instance itself is returned.

class DataDes:
def init(self):
pass
def get(self,instance,owner):
print('DataDes.get')
def set(self,instance,value):
print('DataDes.set',value)
class DataDes_noget:
def init(self):
pass
def set(self,instance,value):
print('DataDes_noget.set',value)
class non_DataDes:
def init(self):
pass
def get(self,instance,owner):
print('non_DataDes.get')
class Manage:
datades = DataDes ()
data_noget = DataDes_noget ()
non_data = non_DataDes ()
"" "

a = Manage()
a.dict
{}

Is there a difference between __get__

a.datades,a.data_noget
DataDes.get #调用__get__
(None, <main.DataDes_noget object at 0x00000000031D5080>, None)#返回实例
a.dict['data_noget'],a.dict['datades'] = 1,2
a.dict
{'data_noget':1,'datades':2}
a.data_noget,a.datades
2 #调用__getattribute__
DataDes.get #调用__get__

Is there a difference between __set__

a.dates = 1
DateDes. set 1 # 调用 __set__
a.datades
DateDes. get
a.non_data
non_DataDes. get
a.non_data = 2 # 调用 __setattribute__
a.non_data
2
a. dict
{'non_data': 2}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324939795&siteId=291194637