【问题标题】:Descriptors and python-provided attributes描述符和 python 提供的属性
【发布时间】:2012-05-19 04:12:37
【问题描述】:

我正在学习 Python,并且正在尝试更好地理解描述符。当我看这本 Python 在线书:http://www.cafepy.com/article/python_attributes_and_methods/ch01s05.html 时,它说:

  1. 如果 attrname 是 objectname 的特殊(即 Python 提供的)属性,则返回它。

我不明白 Python 提供的含义。谁能给我一个 Python 提供的属性的示例,该属性优先于通常的解析顺序?

注意:我只对新式类感兴趣(据我所知,描述符甚至不适用于旧式)。

【问题讨论】:

    标签: python descriptor new-style-class


    【解决方案1】:

    __class__,例如:

    >>> class Test(object):
        __dict__ = {'__class__' : "dict of Test"}
        def __init__(self):
            self.__dict__['__class__'] = "dict of test"
    
    
    >>> test = Test()
    >>> test.__class__
    <class '__main__.Test'>
    >>> test.__dict__
    {'__class__': 'dict of test'}
    >>> Test.__dict__
    dict_proxy({'__dict__': {'__class__': 'dict of test'}, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, '__init__': <function __init__ at 0x02BD2770>})
    >>> 
    

    在旧式类中等效:

    >>> class Test:
            pass
    
    >>> Test.__dict__["__class__"] = "spam"
    >>> test = Test()
    >>> test.__class__
    <class __main__.Test at 0x02BD1110>
    >>> test.__dict__ = {'__class__': "foo"}
    >>> test.__class__
    <class __main__.Test at 0x02BD1110>
    

    同时

    >>> test.__dict__ = {'__lolcat__': "bar"}
    >>> test.__lolcat__
    'bar'
    

    还有更多特殊的属性名称,具体取决于对象的类型。 比如函数:

    >>> def test():pass
    
    >>> dir(test)
    ['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
    >>> test.func_closure
    >>> test.__dict__['func_closure']='roflcopter'
    >>> test.func_closure
    >>> test.__dict__['foo']='bar'
    >>> test.foo
    'bar'
    

    请参阅http://docs.python.org/reference/datamodel.html 了解概览

    【讨论】:

    • 我之前没有意识到这一点,但是直接修改一个类的__dict__ 似乎不适用于新式类——它会导致TypeError: 'dict_proxy' object does not support item assignment。通过修改实例的__dict__,即test.__dict__["__class__"] = "spam",仍然可以在python 3中看到上述行为。另外,你知道还有哪些其他属性是这样工作的吗?我发现的唯一另一个是__dict__ 本身。
    • 我的问题是关于新式课程,您演示的仅适用于旧式课程。
    • 嗯,实际上,这是正常的分辨率顺序。正如预期的那样,它从对象字典中的数据描述符中获取值。 test = Test() print("__class__" in type(test).__dict__) # Looking for a descriptor in the classes __dict__: false print("__class__" in object.__dict__) # Same with parent class: true print(object.__dict__["__class__"].__get__) # It's a descriptor print(object.__dict__["__class__"].__set__) 你的例子并没有表明它被区别对待。
    • 现在我很困惑。结帐:&gt;&gt;&gt; class Test(object): __class__ = "dict of Test" def __init__(self): self.__dict__['__class__'] = "dict of test",然后是&gt;&gt;&gt; test.__class__ 'dict of test',所以看起来 class 一点都不特别?! OTOH,&gt;&gt;&gt; Test.__class__ &lt;type 'type'&gt;我现在有点困惑
    • 这似乎与本书相矛盾,因为如果__class__ 不是特殊的,那么当objname 具有非类.__class__ 时,第二步中的代码如何查找objectname.__class__.__dict__?在我看来,__class__ 必须让这个算法发挥作用。
    【解决方案2】:

    如您所料,第 1 步完全错误且不存在。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多