【问题标题】:How does a classmethod object work?类方法对象如何工作?
【发布时间】:2010-12-13 05:51:35
【问题描述】:

我很难理解类方法对象在 Python 中的工作原理,尤其是在元类和 __new__ 的上下文中。在我的特殊情况下,当我遍历分配给__new__members 时,我想获得一个类方法成员的名称。

对于普通方法,名称只是存储在__name__ 属性中,但对于类方法,显然没有这样的属性。我什至看不到 classmethod 是如何被调用的,因为也没有 __call__ 属性。

有人可以向我解释一个类方法是如何工作的或指向我一些文档吗?谷歌搜索让我无处可去。谢谢!

【问题讨论】:

  • 我不了解“缺失”__name__,但要确保类方法具有 __call__ 包装器。

标签: python metaclass class-method


【解决方案1】:

classmethod 对象是一个描述符。您需要了解描述符的工作原理。

简而言之,描述符是具有__get__ 方法的对象,该方法接受三个参数:selfinstanceinstance type

在普通属性查找期间,如果查找的对象A 具有方法__get__,则调用该方法并将其返回的内容替换为对象A。这就是当您在对象上调用方法时,函数(也是描述符)成为绑定方法的方式。

class Foo(object):
     def bar(self, arg1, arg2):
         print arg1, arg2

foo = Foo()
# this:
foo.bar(1,2)  # prints '1 2'
# does about the same thing as this:
Foo.__dict__['bar'].__get__(foo, type(foo))(1,2)  # prints '1 2'

classmethod 对象的工作方式相同。当它被查找时,它的__get__ 方法被调用。类方法的__get__ 丢弃与instance 对应的参数(如果有的话),并且仅在它调用包装函数上的__get__ 时传递instance_type

说明性涂鸦:

In [14]: def foo(cls):
   ....:     print cls
   ....:     
In [15]: classmethod(foo)
Out[15]: <classmethod object at 0x756e50>
In [16]: cm = classmethod(foo)
In [17]: cm.__get__(None, dict)
Out[17]: <bound method type.foo of <type 'dict'>>
In [18]: cm.__get__(None, dict)()
<type 'dict'>
In [19]: cm.__get__({}, dict)
Out[19]: <bound method type.foo of <type 'dict'>>
In [20]: cm.__get__({}, dict)()
<type 'dict'>
In [21]: cm.__get__("Some bogus unused string", dict)()
<type 'dict'>

有关描述符的更多信息可以在此处(以及其他地方)找到: http://users.rcn.com/python/download/Descriptor.htm

对于获取由classmethod包裹的函数名称的具体任务:

In [29]: cm.__get__(None, dict).im_func.__name__
Out[29]: 'foo'

【讨论】:

  • 谢谢,解决了我的问题!我现在觉得有点愚蠢,因为原则上我知道描述符。但是我很困惑地看到一个类方法被包装在一个不可调用的描述符中:-)
  • 对不起,我忘了强调我非常感谢你非常详细的回答,这太好了。
  • 那个描述符链接消失了 404。
  • .im_func 在 python 3 中现在是 __func__source: 2to3
猜你喜欢
  • 1970-01-01
  • 2012-05-09
  • 2019-01-12
  • 1970-01-01
  • 2021-04-12
  • 2014-05-01
  • 2018-01-16
  • 1970-01-01
  • 2017-02-25
相关资源
最近更新 更多