用@staticmethod修饰的方法和用@classmethod修饰的方法有什么区别?
当前回答
python官方文档:
@分类法
类方法将类作为隐式第一个参数,就像instance方法接收该实例。要声明类方法,请使用成语:C类:@分类法定义f(cls,arg1,arg2,…):。。。@classmethod表单是一个函数decorator–请参见函数中的函数定义详细定义。它可以在类上调用(例如C.f())或实例(例如C().f())。实例是除了它的类之外,都被忽略。如果类方法用于派生类,派生类对象是作为隐含的第一个参数传递。类方法不同于C++或Java静态方法。如果你愿意这些,请参见本文中的staticmethod()部分
@静态方法
静态方法不接收隐式第一个参数。声明静态方法,使用这个成语:C类:@静态方法定义f(arg1,arg2,…):。。。@staticmethod表单是一个函数decorator–请参见函数中的函数定义详细定义。它可以在类上调用(例如C.f())或实例(例如C().f())。实例是除了它的类之外,都被忽略。Python中的静态方法类似类似于Java或C++中的那些。对于更高级的概念,请参见classmethod()。
其他回答
关于如何在Python中使用静态、类或抽象方法的权威指南是本主题的一个很好的链接,总结如下。
@staticmethod函数只不过是在类中定义的函数。它可以在不首先实例化类的情况下调用。它的定义通过继承是不可变的。
Python不必为对象实例化绑定方法。它简化了代码的可读性,并且不依赖于对象本身的状态;
@classmethod函数也可以在不实例化类的情况下调用,但它的定义遵循子类,而不是父类,通过继承,可以被子类重写。这是因为@classmethod函数的第一个参数必须始终是cls(class)。
工厂方法,用于使用例如某种预处理为类创建实例。静态方法调用静态方法:如果将静态方法拆分为多个静态方法,则不应硬编码类名,而应使用类方法
让我先告诉一下用@classmethod修饰的方法和@staticmethod修饰的方法之间的相似性。
相似性:它们都可以在类本身上调用,而不仅仅是类的实例。所以,在某种意义上,这两种方法都是Class的方法。
区别:类方法将接收类本身作为第一个参数,而静态方法不接收。
因此,在某种意义上,静态方法并不绑定到类本身,只是因为它可能具有相关功能而挂在那里。
>>> class Klaus:
@classmethod
def classmthd(*args):
return args
@staticmethod
def staticmthd(*args):
return args
# 1. Call classmethod without any arg
>>> Klaus.classmthd()
(__main__.Klaus,) # the class gets passed as the first argument
# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')
# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()
()
# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
一个非常重要的实际差异发生在子类化时。如果你不介意的话,我会劫持@unsubu的例子:
class A:
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)
class B(A):
pass
在class_foo中,该方法知道它是在哪个类上调用的:
A.class_foo(1)
# => executing class_foo(<class '__main__.A'>, 1)
B.class_foo(1)
# => executing class_foo(<class '__main__.B'>, 1)
在static_foo中,无法确定它是在A还是B上调用的:
A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)
注意,这并不意味着您不能在静态方法中使用其他方法,您只需直接引用类,这意味着子类的静态方法仍将引用父类:
class A:
@classmethod
def class_qux(cls, x):
print(f"executing class_qux({cls}, {x})")
@classmethod
def class_bar(cls, x):
cls.class_qux(x)
@staticmethod
def static_bar(x):
A.class_qux(x)
class B(A):
pass
A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
静态方法是一种对所调用的类或实例一无所知的方法。它只获取传递的参数,而不是隐式的第一个参数。它在Python中基本上是无用的——您可以只使用模块函数而不是静态方法。
另一方面,类方法是一种方法,它将被调用的类或被调用的实例的类作为第一个参数传递。当您希望该方法成为类的工厂时,这很有用:因为它获得了作为第一个参数调用的实际类,所以即使涉及子类,您也可以始终实例化正确的类。例如,观察类方法dict.fromkeys()在子类上调用时如何返回子类的实例:
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
Python带有几个内置的装饰器。三大类是:
@classmethod
@staticmethod
@property
首先,让我们注意,类的任何函数都可以用这个类的实例调用(在初始化这个类之后)。
@classmethod是一种方法,它不仅可以作为类的实例调用函数,还可以直接由类本身作为其第一个参数调用函数。
@staticmethod是一种将函数放入类的方法(因为它在逻辑上属于类),同时表示它不需要访问类(因此我们不需要在函数定义中使用self)。
让我们考虑一下以下课程:
class DecoratorTest(object):
def __init__(self):
pass
def doubler(self, x):
return x*2
@classmethod
def class_doubler(cls, x): # we need to use 'cls' instead of 'self'; 'cls' reference to the class instead of an instance of the class
return x*2
@staticmethod
def static_doubler(x): # no need adding 'self' here; static_doubler() could be just a function not inside the class
return x*2
让我们看看它是如何工作的:
decor = DecoratorTest()
print(decor.doubler(5))
# 10
print(decor.class_doubler(5)) # a call with an instance of a class
# 10
print(DecoratorTest.class_doubler(5)) # a direct call by the class itself
# 10
# staticmethod could be called in the same way as classmethod.
print(decor.static_doubler(5)) # as an instance of the class
# 10
print(DecoratorTest.static_doubler(5)) # or as a direct call
# 10
这里您可以看到这些方法的一些用例。
奖金:您可以在这里阅读@property decorator