为什么没有为实例属性调用__get__方法?

时间:2013-07-13 14:09:54

标签: python python-3.x

有这段代码:

class A:
  def __init__(self, x):
    self.x = x

  def __get__(self, obj, type=None):
    print("__get__")
    return self.x

  def __set__(self, obj, value):
    pass

class B:
  a_oc = A(44)
  def __init__(self, y):
    self.a_ob = A(y)

b = B(3)
print(b.a_oc) # class attribute called __get__
print(b.a_ob) # __get__ not called

对于类属性__get__被调用,例如属性不是。为什么呢?

1 个答案:

答案 0 :(得分:2)

新类型的属性查找规则(3.x中的类和继承自2.x中的对象的类)是obj.attr

  1. 如果该值由Python生成,例如__hash__,则将其返回

  2. obj.__class__.__dict__中查找,如果存在且存在__get__,则返回attr.__get__(obj, obj.__class__)的结果,如果不存在,则递归查找父类。

  3. obj.__dict__中查找。如果obj是实例并且attr存在,则返回它或下一步。如果obj是一个类,则查找其自身,其父项为__dict__,如果是描述符,则返回attr.__get__(None, obj.__class__)或attr本身。

  4. obj.__class__.__dict__中查找。如果attr是非数据描述符,则返回它的结果。如果它存在,则返回attr本身。

  5. 引发AttributeError

  6. 见上课:

    >>> b.__class__
    <class 'des.B'>
    >>> b.__class__.__dict__
    mappingproxy({'__init__': <function B.__init__ at 0x7f2dacb4e290>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__dict__': <attribute '__dict__' of 'B' objects>, 'a_oc': <des.A object at 0x7f2dacb5de50>, '__module__': 'des', '__qualname__': 'B'})
    >>> 
    >>> b.__dict__
    {'a_ob': <des.A object at 0x7f2dacb5df10>}
    >>> 
    

    b.a_oc符合第2步,b.a_ob符合第3步。我将您的代码放在模块des中。