【问题标题】:Why does a descriptor __get__ have access to the object's type but __set__ does not?为什么描述符 __get__ 可以访问对象的类型而 __set__ 没有?
【发布时间】:2017-11-04 19:51:29
【问题描述】:

来自https://docs.python.org/2/howto/descriptor.html

descr.__get__(self, obj, type=None) --> value

descr.__set__(self, obj, value) --> None

descr.__delete__(self, obj) --> None

为什么__get__ 方法可以访问type 而其他两个没有?

【问题讨论】:

  • 我很确定答案隐藏在here 中,但我无法完全确定。
  • 来自Learning Python一书:__get__ 访问方法另外接收一个所有者参数,指定描述符实例附加到的类。它的实例参数要么是访问属性的实例(对于 instance.attr ),要么是通过所有者类直接访问属性时的 None (对于 class.attr )。前者通常为实例访问计算一个值,如果支持描述符对象访问,后者通常返回self
  • 那么为什么__set____delete__ 不会发生同样的事情呢?
  • 我猜这是因为当你设置或删除一个的某些属性时,你只是简单地设置/删除它而不通过描述符?

标签: python python-2.7 descriptor


【解决方案1】:

__get__ 中,type 参数是类名,这在通过类访问属性时很有帮助,因为在这种情况下obj(实例)将是None。在__set__ 中,您不需要type 参数,因为无法通过类设置描述符的值,您只会用新值覆盖描述符。

考虑下面的代码

class RevealAccess(object):
    """A data descriptor that sets and returns values
       normally and prints a message logging their access.
    """

    def __init__(self, initval=None, name='var'):
        self.val = initval
        self.name = name

    def __get__(self, obj, objtype):
        print 'Retrieving', self.name
        return self.val

    def __set__(self, obj, val):
        print 'Updating', self.name
        self.val = val

>>> class MyClass(object):
...     x = RevealAccess(10, 'var "x"')
...     y = 5
...
>>> m = MyClass()
>>> m.x
Retrieving var "x"
10
>>> m.x = 20
Updating var "x"
>>> MyClass.x  # accessing descriptor x through class
Retrieving var "x"
20
>>> MyClass.x = 20  # class parameter x is overwritten with value 20, it's not a descriptor any more
>>>

【讨论】:

  • 确实,__get__ 具有不同寻常的状态,因为它既可以作为实例方法也可以作为类方法工作,具体取决于访问描述符的方式。
  • 不是“正常”设置和检索值。您将它们设置在描述符 itself 上,该描述符在 MyClass! 的所有实例之间共享
猜你喜欢
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
  • 2015-06-08
  • 1970-01-01
相关资源
最近更新 更多