@classmethod和@staticmethod在Python中是什么意思,它们有什么不同?我应该何时使用它们,为什么要使用它们,以及如何使用它们?
据我所知,@classmethod告诉一个类,它是一个应该继承到子类中的方法,或者。。。某物然而,这有什么意义?为什么不直接定义class方法而不添加@classmethod或@staticmethod或任何@定义?
@classmethod和@staticmethod在Python中是什么意思,它们有什么不同?我应该何时使用它们,为什么要使用它们,以及如何使用它们?
据我所知,@classmethod告诉一个类,它是一个应该继承到子类中的方法,或者。。。某物然而,这有什么意义?为什么不直接定义class方法而不添加@classmethod或@staticmethod或任何@定义?
当前回答
一种稍微不同的思考方式可能对某人有用。。。在超类中使用类方法来定义该方法在被不同的子类调用时的行为。当我们想要返回相同的东西而不管我们调用的子类是什么时,就使用静态方法。
其他回答
一个小汇编
@静态方法一种在类中编写方法的方法,而不引用它所调用的对象。因此不需要传递self或cls之类的隐式参数。它的编写方式与在类外部的编写方式完全相同,但在python中没有任何用处,因为如果您需要在类内部封装方法,因为该方法需要是该类的一部分,那么@staticmethod在这种情况下很方便。
@分类法当你想写一个工厂方法并且通过这个自定义属性可以附加在一个类中时,这一点很重要。可以在继承的类中重写此属性。
这两种方法的比较如下
@分类法
@classmethod可以与__init__进行比较。你可以认为这是另一个__init__()。这是python在c++中实现类构造函数重载的方式。
class C:
def __init__(self, parameters):
....
@classmethod
def construct_from_func(cls, parameters):
....
obj1 = C(parameters)
obj2 = C.construct_from_func(parameters)
注意,它们都有一个类的引用作为definitioin中的第一个参数,而init_使用self,但constructfrom_func使用cls。
@静态方法
@静态方法可以与对象方法进行比较
class C:
def __init__(self):
....
@staticmethod
def static_method(args):
....
def normal_method(parameters):
....
result = C.static_method(parameters)
result = obj.normal_method(parameters)
类方法可以修改类状态,它绑定到类并且包含cls作为参数。
静态方法不能修改类状态,它绑定到类,它不知道类或实例
class empDetails:
def __init__(self,name,sal):
self.name=name
self.sal=sal
@classmethod
def increment(cls,name,none):
return cls('yarramsetti',6000 + 500)
@staticmethod
def salChecking(sal):
return sal > 6000
emp1=empDetails('durga prasad',6000)
emp2=empDetails.increment('yarramsetti',100)
# output is 'durga prasad'
print emp1.name
# output put is 6000
print emp1.sal
# output is 6500,because it change the sal variable
print emp2.sal
# output is 'yarramsetti' it change the state of name variable
print emp2.name
# output is True, because ,it change the state of sal variable
print empDetails.salChecking(6500)
罗斯季斯拉夫·德津科的回答非常恰当。我想我可以强调另一个原因,当您创建一个额外的构造函数时,您应该选择@classmethod而不是@staticmethod。
在本例中,Rostyslav使用@classmethodfrom_string作为Factory,从其他不可接受的参数创建Date对象。使用@staticmethod也可以做到这一点,如下代码所示:
class Date:
def __init__(self, month, day, year):
self.month = month
self.day = day
self.year = year
def display(self):
return "{0}-{1}-{2}".format(self.month, self.day, self.year)
@staticmethod
def millenium(month, day):
return Date(month, day, 2000)
new_year = Date(1, 1, 2013) # Creates a new Date object
millenium_new_year = Date.millenium(1, 1) # also creates a Date object.
# Proof:
new_year.display() # "1-1-2013"
millenium_new_year.display() # "1-1-2000"
isinstance(new_year, Date) # True
isinstance(millenium_new_year, Date) # True
因此,new_year和million_new_year都是Date类的实例。
但是,如果您仔细观察,Factory过程是硬编码的,无论是什么都可以创建Date对象。这意味着,即使Date类是子类,子类仍将创建普通的Date对象(没有子类的任何财产)。请参见以下示例:
class DateTime(Date):
def display(self):
return "{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)
datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)
isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # False
datetime1.display() # returns "10-10-1990 - 00:00:00PM"
datetime2.display() # returns "10-10-2000" because it's not a DateTime object but a Date object. Check the implementation of the millenium method on the Date class for more details.
datetime2不是DateTime的实例?世界跆拳道联盟?这是因为使用了@staticmethoddecorator。
在大多数情况下,这是不希望的。如果你想要的是一个知道调用它的类的Factory方法,那么@classmethod就是你需要的。
将Date.millenium重写为(这是上述代码中唯一更改的部分):
@classmethod
def millenium(cls, month, day):
return cls(month, day, 2000)
确保课程不是硬编码的,而是学习的。cls可以是任何子类。结果对象将是cls的实例。让我们测试一下:
datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)
isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # True
datetime1.display() # "10-10-1990 - 00:00:00PM"
datetime2.display() # "10-10-2000 - 00:00:00PM"
原因是,正如您现在所知,使用了@classmethod而不是@staticmethod
一种稍微不同的思考方式可能对某人有用。。。在超类中使用类方法来定义该方法在被不同的子类调用时的行为。当我们想要返回相同的东西而不管我们调用的子类是什么时,就使用静态方法。