非凡 发表于 2021-8-15 17:10:30

关于对象描述符问题

class MyDes:
    def __init__(self,number,writ):
      self.number = number
      self.writ = writ

    def __get__(self, instance, owner):
      print('现在获取变量%s' %self.writ)
      return self.number

    def __set__(self, instance, value):
      print('变量%s在修改' %self.writ)
      self.number = value

    def __delete__(self, instance):
      print('正在山删除%s'%self.writ)
      print('变量:x删不了。')
class Test:
    x = MyDes(10,'x')

test = Test()





上面代码正常运行后,正常调用x,何修改x。

>>> test.x
现在获取变量x
10
>>> test.x = 1
变量x在修改

但我有想法,能不嫩创建个变量y能,然后实现上面变量x一样的功能。
>>> test.y = MyDes(4,'y')
>>> test.y
<__main__.MyDes object at 0x0000020C3CC3B848>
>>> test.y = 23
>>> test.y
23
>>>

1、为什么会失败?原因在哪?
2、我这想法能实现吗?

Twilight6 发表于 2021-8-15 17:10:31


1、为什么会失败?原因在哪?

因为描述符只有作用在 类 层面上,Python 才会自动调用描述符的 __get__ 和 __set__

而此时你的 test 是 Test 类的实例对象,那么 test.y = MyDes(4, 'y') 实际上是在创建一个 实例属性,即类中带 self.变量名 的属性,而不是类层面上的属性

2、我这想法能实现吗?

可以实现,你只需将赋值过程用实例对象改成用类本身即可,如下代码:

Test.y = MyDes(4,'y')

即可成功创建了描述符,此时你在对实例进行 test.y 就能发现获取成功

kogawananari 发表于 2021-8-15 19:38:12

1 描述符只能给类捆绑 实例化对象不能捆绑
2 能实现 可以不用描述符 使用代理类最简单

阿奇_o 发表于 2021-8-15 23:11:09

本帖最后由 阿奇_o 于 2021-8-15 23:16 编辑

这么说吧,"描述符",本身是为了"描述另一个类的特殊类"。

1. 特殊?特殊在哪?—— 特殊在它 有 __get__, __set__, __delete__, 这几个特殊方法,有这其一 就是"描述符"(__set_name__ 也可选)
    其次,还特殊在 要写正确这几个方法,必须遵守"描述器协议"(就是它的特定参数列表各需要写什么)

2. 描述另一个类?描述什么?—— 另一个类(或说是描述器的"owner")的【类变量】——该类的类变量指向描述器类对象
    这就好比,身残志坚某某作家,自己不能亲自写文章(类变量),但他请了打字员小王帮它写,
    这里小王就是"描述器",他和这个作家之间的协议约定就是"描述器协议"。
    —— 这里的关键是 必须是 类变量, 必须是 在类定义里 把类变量指向一个描述器类对象,如 x = MyDesp('小王')   
    —— 注意:若你写 实例变量 self.y = MyDesp('小王') 是没用的,描述器只针对 类变量

希望对你有帮助。

页: [1]
查看完整版本: 关于对象描述符问题