Python - classmethod()

时间:2014-02-19 11:47:05

标签: python generator standard-library class-method

阅读Python标准库。试图理解类方法。

class C:
    @classmethod
    def f(x,y):
        print('words')

当我输入:

print(classmethod(C))

它返回:

<classmethod object at 0x00FAD930>

如何看到classmethod返回的内容而不是classmethod的生成器?

4 个答案:

答案 0 :(得分:3)

您正在生成classmethod描述符对象:

print(classmethod(C))

返回包含在新C对象中的类classmethod。这不是一个生成器,当你用它装饰一个方法时,这就是Python实际存储在你的类中。

请记住,函数或类上方的@decorator_expression行只是替换该对象的额外函数调用的语法糖; @classmethod以上def f(...)只表示Python会将f替换为f = classmethod(f)

在查看C.__dict__['f']值时,您可以看到相同类型的对象;这是同一类型的对象:

>>> class C:
...     @classmethod
...     def f(x,y):
...         print('words')
... 
>>> C.__dict__['f']
<classmethod object at 0x107d00810>
>>> C.__dict__['f'].__get__(None, C)
<bound method type.f of <class '__main__.C'>>
>>> C.f
<bound method type.f of <class '__main__.C'>>

当您尝试访问__get__属性时,调用描述符对象的C.f方法。

函数本身也是描述符; a classmethod绕过函数的.__get__方法,以提供对类的绑定,而不是对实例的正常绑定。

请参阅descriptor HOWTO以了解描述符的内容以及classmethod对象的工作原理。

要查看方法本身返回的内容,只需在类或实例上调用它:

>>> class C:
...     @classmethod
...     def f(*args, **kw):
...         return args, kw
...     def regular(*args, **kw):
...         return args, kw
... 
>>> C.f()
((<class '__main__.C'>,), {})
>>> C().f()
((<class '__main__.C'>,), {})
>>> C.regular()
((), {})
>>> C().regular()
((<__main__.C object at 0x1085b0790>,), {})

而不是通常的self实例对象,而是传递对该类的引用。对于C.f()调用(直接在类上)和C().f()(在C的实例上),f()的第一个参数是C本身

将此与C.regular()方法进行比较;这是一个普通的方法,当直接在具有C.regular()的类上调用时,没有传入参数,当在C().regular()的实例上调用第一个参数时,实例被传入。这就是你通常会在方法签名中使用self

对于类方法,在声明方法时,第一个参数通常被命名为cls

答案 1 :(得分:2)

如果您想拨打classmethod上创建的f C,请执行以下操作:

C.f(...)

classmethod是装饰器函数,它将包装传递给它的任何内容并返回classmethod object

>>> classmethod(1)
<classmethod object at 0x02FA6370>

请注意,classmethod的第一个是类本身,按惯例称为cls

class C:
    @classmethod
    def f(cls, x, y):
        print("words")

这给出了:

>>> C.f(1, 2)
words

另外,return值和print在函数外部:

class C:
    @classmethod
    def f(cls, x, y):
        return "words"

>>> print(C.f(1, 2))
words

答案 2 :(得分:0)

更改为:

class C:
    @classmethod
    def f(cls, x, y):
        return 'words'

与第一个参数是self引用的传统类方法不同,类方法接收class作为隐式第一个参数,就像实例方法接收实例一样。

此外,您需要返回一个值来打印它。

答案 3 :(得分:0)

在所有正在创建的不同对象之间共享值时,classmethod非常有用。

class Classtest:
    a =10
    @classmethod
    def hi(cls, x):
        cls.a= cls.a+x
        print cls.a

h = Classtest()
h.hi(10)

b = Classtest()
b.hi(30)

c = Classtest()
c.hi(40)

>>> ================================ RESTART     ================================
>>>  
20
50
90

这里变量a的值在所有正在创建的不同对象之间共享,而不仅限于一个实例