为什么我们使用@staticmethod?

时间:2014-05-07 03:35:02

标签: python

我无法理解为什么我们需要使用@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的禅宗声明“明确比隐含更好”?

4 个答案:

答案 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与类File1File2密切相关,因此将其放入类中更为自然。但是,在某些情况下,有时这种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,您有三个选择:

  1. 把它放在课外。但我们决定反对这一点。

  2. 不做任何新事:未使用时,仍保留self参数。

  3. 声明您未使用self参数,同时仍允许其他C方法将f称为self.f,如果您希望继续保持f进一步覆盖取决于某些实例状态的可能性。

  4. 选项2要求较少的概念包袱(您必须了解self和方法作为约束函数,因为它是更一般的情况)。但你仍然可能更愿意明确self没有使用(并且解释器甚至可以通过一些优化奖励你,而不必将功能部分地应用于self)。在这种情况下,您选择选项3并在函数顶部添加@staticmethod