繁体   English   中英

类实例上元类的方法

[英]methods of metaclasses on class instances

我想知道在元类上声明的方法会发生什么。 我希望如果你在元类上声明一个方法,它最终将成为一个类方法,但是,行为是不同的。

>>> class A(object):
...     @classmethod
...     def foo(cls):
...         print "foo"
... 
>>> a=A()
>>> a.foo()
foo
>>> A.foo()
foo

但是,如果我尝试定义一个元类并给它一个方法foo,它似乎对类有效,而不是对于实例。

>>> class Meta(type): 
...     def foo(self): 
...         print "foo"
... 
>>> class A(object):
...     __metaclass__=Meta
...     def __init__(self):
...         print "hello"
... 
>>> 
>>> a=A()
hello
>>> A.foo()
foo
>>> a.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'foo'

这到底发生了什么?

编辑 :碰撞问题

你提出了一个好点。

这是一个很好的参考 ,可以更好地理解对象,类和元类之间的关系:

我也发现这个关于描述符的引用对于 python中的查找机制非常有启发性。

但我不能说我理解为什么当A.foo成功时A.foo a.foo失败。 看起来,当你查找一个对象的属性,并且python在那里找不到它时,它并没有完全查找类中的属性,因为如果它发生了,它会找到A.foo

编辑:

哦! 我想我明白了。 这是由于继承如何工作。 如果您考虑上述链接提供的架构,它看起来像这样:

替代文字

原理上,它归结为:

type -- object
  |       |
Meta --   A  -- a

左转意味着转到给定实例的类。 上升意味着去父母

现在,继承机制使查找机制在上面的模式中向右转 它变成a → A → object 它必须这样做才能遵循继承规则! 为清楚起见,搜索路径是:

 object
   ^
   |
   A  <-- a

然后,显然,将找不到属性foo

当你查找的属性fooA ,但是,人们发现 ,由于查找路径是:

type
  ^
  |       
Meta <--   A 

当人们想到继承如何运作时,这一切都是有意义的。

规则是这样的:当在对象上搜索属性时,也考虑对象的类及其父类。 但是, 考虑对象的类的元类。 当你访问一个类的属性,类的类是元类,因此它认为。 从对象到其类的回退不会触发对类的“正常”属性查找:例如,无论是在实例上还是在其类上访问属性,都会以不同方式调用描述符。

方法是可调用的属性(并且具有__get__方法,使得'self'自动传递。)这使得如果在类上调用它们但在实例上不可用,则元类上的方法就像classmethods。

我理解它的方式是Meta是一个类,A是它的一个实例。 因此,当您调用A.foo()时,它会检查对象及其类。 因此,在尝试A.foo时,它首先查看A本身持有的方法,然后查看其类的方法Meta。 因为A本身没有方法foo,所以它使用Meta之一,因此真正执行Meta.foo(A)。

类似地,当尝试a.foo时,它将首先查看a。 作为一个没有方法foo,它将通过A看。但是A也没有方法foo,因为foo在Meta中保存。 由于a和A都不包含foo,因此会引发AttributeError。

我尝试使用变量和函数,在类Meta中加入属性txt ='txt',这也可以由A访问,但不是a。 所以,我倾向于认为我的理解是正确的,但我只是在猜测。

已接受答案中的链接已经消失,至少对我而言。 所以我想做一些补充:

3.数据模型 - 对象.__ getattribute__

并在我看来给出两个关键点:

  • object.__getattribute__控件实例的属性访问。
  • type.__getattribute__控件类的属性访问。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM