python 关于 Descriptor 的小问题,我覆盖了 object 的__getattribute__方法但是描述器依然有用啊?

2016-08-17 15:09:30 +08:00
 petelin

我搞不明白为什么类里面定义 a = CLASS() , 然后调用 class.a 就能直接得到值。

我去看官方的how to,里面意思是

  1. descriptors are invoked by the getattribute() method
  2. overriding getattribute() prevents automatic descriptor calls
class B(object):
    def __getattribute__(self, key):
        print('getattribute %s  %s' % (self, key,))
        return 3

    def __getattr__(self, item):
        print('getattr.........')
        return 1

    def __get__(self, instance, owner):
        print('get..........')
        print(self, instance, owner)
        return 2
class C():
    b = B()
print(C().b)

这个直接调用的__get__啊,彻底乱了,我看他写的太费劲了,有没有别的文章,我参考下?高手快出现~~~

2405 次点击
所在节点    Python
6 条回复
petelin
2016-08-17 15:17:05 +08:00
我好像明白了, getattribute 是定义在 C 里面的,,,他决定在 b 被调用的时候,到底怎么返回什么!!!这样就顺了,我说为什么,直接 B ()返回的是对象, C.b 返回的是__get__的结果。
glasslion
2016-08-17 15:21:24 +08:00
你理解错文档的意思了, 把 __getattribute__, __getattr__ 移到 class C 里
petelin
2016-08-17 15:43:45 +08:00
@petelin 描述器太黑了,,,喜欢 python 的一定要去看看,解决了我很多问题,我说一个函数怎么好端端的就变成方法了,还能分出来绑定和非绑定。还有这个一个类当做属性,,,太黑了
aec4d
2016-08-17 18:01:30 +08:00
https://ficapy.github.io/2016/07/10/python_descriptor/
__get__不是直接直接用来访问的.它会单独写在一个类里面,然后将这个对象作为另外一个类的属性(所以不会出现你上面的__get__和其他__getattr__在一起这种情况)
__getattribute__是默认的访问属性的方式.一般不会被重写,可能会这样使用 object.__getattribute__(object 的__getattribute__不可能被重写)
__getattr__表示对象不存在这个属性的时候该怎么做
我觉得 Werkzeug 的 local.py 文件对你的理解可能有一些帮助
https://github.com/pallets/werkzeug/blob/master/werkzeug/local.py
petelin
2016-08-17 18:46:24 +08:00
@aec4d 感谢回复,看了之后清楚多了,关于__getattribute__我还有点问题,他和 self.__dict__什么关系,我试图在一个类里描述 object 的__getattribute__的时候总是不成功,递归调用了
```
def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = self.__dict__[key]
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v
```


官方给那个实现,他解释 object 的 getatrribute 方法却调用了那个方法,没什么用啊
```
def __getattribute__(self, key):
"Emulate type_getattro() in Objects/typeobject.c"
v = object.__getattribute__(self, key)
if hasattr(v, '__get__'):
return v.__get__(None, self)
return v
```

所以__getattribute__只能是用 c 语言描述的? 我在 getattribute 里面调用__dict__为啥会递归呢,__dict__不是一个简单的 dict 吗?
aec4d
2016-08-17 19:37:03 +08:00
@petelin self.__dict__同样要调用 self.__getattribute__,所以造成了无限递归调用
如果你使用 object.__getattribute__就不会有这个问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/299907

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX