我无法理解为什么我们需要使用@staticmethod。让我们从一个例子开始吧。
class test1:
def __init__(self,value):
self.value=value
@staticmethod
def static_add_one(value):
return value+1
@property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
a=test1(3)
print(a.new_val) ## >>> 4
class test2:
def __init__(self,value):
self.value=value
def static_add_one(self,value):
return value+1
@property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
b=test2(3)
print(b.new_val) ## >>> 4
在上面的示例中,两个类中的方法static_add_one
在计算中不需要类(self)的实例。
班级static_add_one
中的方法test1
由@staticmethod
修饰并正常运行。
但与此同时,类static_add_one
中没有test2
装饰的方法@staticmethod
也可以通过使用提供self
的技巧正常工作参数,但根本不使用它。
那么使用@staticmethod
有什么好处?它会改善性能吗?或者仅仅是因为python的禅宗声明“明确比隐含更好”?
答案 0 :(得分:15)
使用staticmethod
的原因是,如果你有一些东西可以写成独立的函数(不是任何类的一部分),但是你想把它保留在类中,因为它在某种程度上在语义上与类相关。 (例如,它可能是一个函数,不需要来自类的任何信息,但其行为特定于类,因此子类可能希望覆盖它。)在许多情况下,它可能同样有意义将某些内容写为独立函数而不是静态方法。
你的例子并不完全相同。一个关键的区别是,即使您不使用self
,仍然需要一个实例来调用static_add_one
---您无法直接在test2.static_add_one(1)
的类上调用它。因此,在那里有一个真正的差异。 static方法最严重的“竞争对手”不是忽略self
的常规方法,而是一个独立的函数。
答案 1 :(得分:2)
今天我突然发现使用@staticmethod
的好处。
如果您在类中创建了静态方法,则在使用static方法之前不需要创建该类的实例。
例如,
class File1:
def __init__(self, path):
out=self.parse(path)
def parse(self, path):
..parsing works..
return x
class File2:
def __init__(self, path):
out=self.parse(path)
@staticmethod
def parse(path):
..parsing works..
return x
if __name__=='__main__':
path='abc.txt'
File1.parse(path) #TypeError: unbound method parse() ....
File2.parse(path) #Goal!!!!!!!!!!!!!!!!!!!!
由于方法parse
与类File1
和File2
密切相关,因此将其放入类中更为自然。但是,在某些情况下,有时这种parse
方法也可能用于其他类。如果要使用File1
执行此操作,则必须在调用方法File1
之前创建parse
的实例。在类File2
中使用staticmethod时,您可以使用语法File2.parse
直接调用该方法。
这使您的作品更加方便和自然。
答案 2 :(得分:0)
对于不需要对特定对象进行操作但仍希望位于类范围内的方法(而不是模块范围),请使用@staticmethod
。
test2.static_add_one
中的示例会浪费时间传递未使用的self
参数,但其他方式与test1.static_add_one
相同。请注意,无法优化此无关参数。
我能想到的一个例子是我所拥有的Django项目,其中模型类表示数据库表,该类的对象表示记录。这个类使用的某些函数是独立的,不需要操作对象,例如将标题转换为“slug”的函数,它是符合字符集限制的标题的表示。 URL语法强加的。将标题转换为slug的函数被声明为staticmethod
,以便将其与使用它的类强烈关联。
答案 3 :(得分:0)
我会补充一些其他答案没有提及的内容。它不仅仅是模块化的问题,而是将其他东西放在其他逻辑相关的部分旁边。还有的是,该方法在层次结构的其他点(即,在子类或超类中)可以是非静态的,因此参与多态性(基于类型的调度)。因此,如果将该函数放在类之外,则会阻止子类有效地覆盖它。现在,假设您发现在课程self
的功能C.f
中不需要C
,您有三个选择:
把它放在课外。但我们决定反对这一点。
不做任何新事:未使用时,仍保留self
参数。
声明您未使用self
参数,同时仍允许其他C
方法将f
称为self.f
,如果您希望继续保持f
进一步覆盖取决于某些实例状态的可能性。
选项2要求较少的概念包袱(您必须了解self
和方法作为约束函数,因为它是更一般的情况)。但你仍然可能更愿意明确self
没有使用(并且解释器甚至可以通过一些优化奖励你,而不必将功能部分地应用于self
)。在这种情况下,您选择选项3并在函数顶部添加@staticmethod
。