Python中@staticmethod和@classmethod有什么区别?

@staticmethod装饰的功能和用@staticmethod装饰的功能有@staticmethod @classmethod


也许有一些示例代码会有帮助:注意fooclass_foostatic_foo的调用签名的static_foo

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x    

a=A()

以下是对象实例调用方法的常用方法。 对象实例a隐式地作为第一个参数传递。

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

在类方法中 ,对象实例的类作为第一个参数隐式传递,而不是self

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

您也可以使用该类调用class_foo 。 事实上,如果你定义了一些类方法,可能是因为你打算从类而不是从类实例中调用它。 A.foo(1)会产生TypeError,但A.class_foo(1)工作得很好:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

人们发现一种用于类方法的方法是创建可继承的替代构造函数。


使用静态方法self (对象实例)和cls (类)都不会作为第一个参数隐式传递。 除了可以从实例或类中调用它们之外,它们的行为与普通函数类似:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

静态方法用于对与类具有某种逻辑连接的函数进行分组。


foo仅仅是一个函数,但是当你调用a.foo你不只是得到的功能,你会得到一个“部分应用”功能与对象实例的版本a绑定作为第一个参数的函数。 foo需要2个参数,而a.foo只需要1个参数。

a必然会成为foo 。 这就是以下“绑定”一词的含义:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

对于a.class_fooa不绑定到class_foo ,而是类A绑定到class_foo

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

在这里,尽管静态方法是一种方法,但a.static_foo只是返回一个没有绑定参数的好的'ole函数。 static_foo需要1个参数,而a.static_foo需要1个参数。

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

当然,当你用class A调用static_foo ,会发生同样的事情。

print(A.static_foo)
# <function static_foo at 0xb7d479cc>

静态方法是一种对它所调用的类或实例一无所知的方法。 它只是获得通过的参数,没有隐含的第一个参数。 在Python中基本没用 - 你可以使用模块函数而不是静态方法。

另一方面,类方法是一种方法,它通过调用它的类或调用的实例的类作为第一个参数传递。 当你希望该方法成为该类的工厂时,这很有用:因为它获得了作为第一个参数被调用的实际类,即使涉及子类,也可以始终实例化正确的类。 例如,观察dict.fromkeys()是一个类方法,它在子类上调用时返回子类的实例:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

基本上@classmethod创建了一个方法,其第一个参数是从其调用的类(而不是类实例), @staticmethod没有任何隐式参数。

链接地址: http://www.djcxy.com/p/167.html

上一篇: What is the difference between @staticmethod and @classmethod in Python?

下一篇: What is the yield keyword used for in C#?