|
发表于 2023-1-10 00:26:29
|
显示全部楼层
数据描述符、非数据描述符、优雅编程
- class D:
- def __get__(self, instance, owner):
- print('get~')
- class C:
- def __init__(self):
- self.x = D()
- c = C()
- print(c.x)# <__main__.D object at 0x0000020FC2EDCFA0>
- #描述符只能应用于类属性,而这里把它应用于对象属性,使用不会打印get~
- class C:
- x = D()
- c = C()
- c.x# get~
- # 数据描述符:实现__set__()和__delete__()中的一个
- # 非数据描述符:仅实现__get__()方法
- # 当发生属性访问的时候,优先级从高到低依次是:数据描述符 -> 实例对象属性 -> 非数据描述符 -> 类属性
- c.x = 'fishc'
- print(c.x)# fishc
- # D为非数据描述符,优先级小于实例对象属性,所以可以更改实例对象的属性
- C.x# get~
- class D:
- def __get__(self, instance, owner):
- print('get~')
- def __set__(self, instance, value):
- print('set~')
- class C:
- x = D()
- c = C()
- c.x = 'FishC'# set~
- c.x# get~
- print(c.__dict__)# {}
- # 数据描述符优先级大于实例对象属性
- c.__dict__['x'] = 'FishC'
- print(c.__dict__)# {'x': 'FishC'}
- c.x# get~
- # 拥有__set__()方法后D为数据描述符,访问对象属性依然执行优先级较高的__get__()
- # 优先级是定义在__getattribute__()魔法方法实现,因为其管理的是属性的获取
- class C:
- x = D()
- def __getattribute__(self, item):
- print('aha~')
- c = C()
- c.x# aha~
- # 没有执行描述符D中的__get__()魔法方法
- #__set_name__(self, name, owner):描述符的第四个魔法方法 ptyhon3.6。
- # 前边的描述符的魔法方法__get__()、__set__()、__delete__()实现的都是对属性的拦截,在实际开发工作中,我们通过描述符去拦截一个属性,然后做了一些额外的工作,之后通常还要执行相应的访问、赋值或删除等操作。
- # 如我们通过描述符拦截了对象的x属性,并进行了合法性验证,判断他的值是不是大于某个值之类的操作,如果符合要求我们仍然要把它写入到实例对象的属性中去,也就是说我们需要在描述符里去操作实例对象的__dict__()字典,这其实是可以做到的,因为instance参数代表的就是描述符所拦截的属性所在的实例对象。
- class D:
- def __init__(self, name):
- self.name = name# name的作用就是记住这个描述符拦截的属性名
- def __get__(self, instance, owner):
- print('get~')
- return instance.__dict__.get(self.name)
- def __set__(self, instance, value):
- print('set~')
- instance.__dict__[self.name] = value
- class C:
- x = D('x')
- c = C()
- c.x# get~
- #__get__()魔法方法拦截成功,此时属性x里没有内容,所以没有返回
- print(c.__dict__)# {}
- c.x = 250# set~
- print(c.__dict__)# {'x': 250}
- print(c.x)
- # get~
- # 250
- # class C中代码x = D('x')不够优雅,传入的属性x是以字符串'x'的形式传入。
- class D:
- def __set_name__(self, owner, name):
- self.name = name# name的作用依然是记住这个描述符拦截的属性名
- def __get__(self, instance, owner):
- print('get~')
- return instance.__dict__.get(self.name)
- def __set__(self, instance, value):
- print('set~')
- instance.__dict__[self.name] = value
- class C:
- x = D()# 优雅~~~
- c = C()
- c.x# get~
- print(c.__dict__)# {}
- c.x = 250# set~
- print(c.__dict__)# {'x': 250}
- print(c.x)
- # get~
- # 250
复制代码 |
|