V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
petelin
V2EX  ›  Python

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

  •  
  •   petelin · 2016-08-17 15:09:30 +08:00 · 2390 次点击
    这是一个创建于 3009 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我搞不明白为什么类里面定义 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__啊,彻底乱了,我看他写的太费劲了,有没有别的文章,我参考下?高手快出现~~~

    6 条回复    2016-08-17 19:37:03 +08:00
    petelin
        1
    petelin  
    OP
       2016-08-17 15:17:05 +08:00
    我好像明白了, getattribute 是定义在 C 里面的,,,他决定在 b 被调用的时候,到底怎么返回什么!!!这样就顺了,我说为什么,直接 B ()返回的是对象, C.b 返回的是__get__的结果。
    glasslion
        2
    glasslion  
       2016-08-17 15:21:24 +08:00   ❤️ 1
    你理解错文档的意思了, 把 __getattribute__, __getattr__ 移到 class C 里
    petelin
        3
    petelin  
    OP
       2016-08-17 15:43:45 +08:00
    @petelin 描述器太黑了,,,喜欢 python 的一定要去看看,解决了我很多问题,我说一个函数怎么好端端的就变成方法了,还能分出来绑定和非绑定。还有这个一个类当做属性,,,太黑了
    aec4d
        4
    aec4d  
       2016-08-17 18:01:30 +08:00   ❤️ 1
    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
        5
    petelin  
    OP
       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
        6
    aec4d  
       2016-08-17 19:37:03 +08:00
    @petelin self.__dict__同样要调用 self.__getattribute__,所以造成了无限递归调用
    如果你使用 object.__getattribute__就不会有这个问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1043 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:48 · PVG 03:48 · LAX 11:48 · JFK 14:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.