3

有这个代码:

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__被调用,例如属性它不是。为什么?

4

1 回答 1

3

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

  1. 如果该值是 Python 生成的,如__hash__,则返回

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

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

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

  5. 引发属性错误

上课见:

>>> 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

于 2013-07-13T14:25:15.233 回答