2014-05-07 54 views
4

我只是不明白为什么我们需要使用@staticmethod。我们从一个例子开始。为什么我们使用@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,在两班不需要在计算中的类(个体)的实例。

该方法static_add_one在类test1装饰@staticmethod和正常工作。

但在同一时间,在没有@staticmethod装修也用了一招,它提供了论据一self,但不会在所有使用它工作正常类test2方法static_add_one

那么使用@staticmethod有什么好处?它是否改善了性能?还是仅仅是由于python的禅宗说明“明确比隐含好”?

+0

大多数情况下,只使用模块级别的函数并忘记存在'@ staticmethod'。 – roippi

+0

让java程序员开心。 – michaelmeyer

+1

@Ignacio Vazquez-Abrams:请问为什么我们不应该使用'test.static_add_one'? –

回答

8

使用staticmethod的原因是,如果你有一些东西可以写成独立函数(不是任何类的一部分),但是你想保留在类中,因为它在语义上与类相关。 (例如,它可能是一个函数,它不需要来自类的任何信息,但其行为是特定于该类的,因此子类可能需要覆盖它。)在许多情况下,它可能同样有意义将某些东西作为独立函数而不是静态方法来编写。

你的例子并不完全相同。一个关键的区别是,即使你不使用self,你仍然需要一个实例来调用static_add_one ---你不能直接在类test2.static_add_one(1)上调用它。所以那里的bejavior有真正的不同。静态方法中最严重的“竞争对手”并不是忽略self而是独立功能的常规方法。

+0

+1这是目标。我们使用静态方法将常规函数附加到类。这改进了与类强相关但不依赖于它的函数的可查找性。 –

+0

所以,如果一个函数具有两个特征 - 独立和语义上与一个类相关。为了服从语义相似性的特征,我应该把它放在一个类中。 为了服从独立的特性,我应该使用'@ staticmethod'装饰器,而不是在其中传递一个虚拟的'self'参数,因为参数'self'以某种方式消失了它的独立颜色。但毕竟,没有太多的性能增益,对吧? –

+0

@ user2720402:粗略地说,是的,如果我理解你的话。性能不是使用或不使用静态方法的原因。您应该根据函数与类的概念关系(或缺少)来选择是否使用静态方法。 – BrenBarn

0

使用@staticmethod表示不需要对特定对象进行操作,但仍然希望位于类范围内(而不是模块范围)的方法。

您在test2.static_add_one中的示例浪费了时间,通过了一个未使用的self参数,但其他功能与test1.static_add_one相同。请注意,这个无关的参数不能优化。

我能想到的一个例子是在我有的Django项目中,模型类表示一个数据库表,并且该类的一个对象表示一个记录。这个类有一些独立使用的函数,不需要一个对象来操作,例如一个将标题转换为“slug”的函数,它是字符集限制之后的标题的表示由URL语法强加。将标题转换为段落的函数声明为staticmethod,正是为了强烈地将其与使用它的类相关联。

0

今天我突然发现使用@staticmethod的好处。

如果您在类中创建了静态方法,则在使用静态方法之前,不需要创建类的实例。

例如,

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,更自然地把它里面的类。但是,在某些情况下,有时这种方法也可能用于其他类。如果您想使用File1执行此操作,则必须在调用方法parse之前创建File1的实例。在类File2中使用静态方法时,可以使用语法File2.parse直接调用该方法。

这使您的作品更加方便自然。

0

我会添加一些其他答案没有提及。这不仅仅是模块化的问题,而是将某些东西放在其他逻辑相关的部分旁边。同样,该方法在层次结构的其他位置(即在子类或超类中)可以是非静态的,因此参与多态(基于类型的调度)。所以如果你把这个函数放在类之外,你将会阻止子类有效地覆盖它。现在,假设你意识到你不C类的功能C.f需要self,你有三种两种选择:

  1. 把它的类之外。但我们只是决定不这样做。

  2. 什么也不做新的:虽然未使用,仍然保持self参数。

  3. 声明你使用的不是self参数,同时还让其他C方法调用fself.f,如果你想保持开放的f进一步覆盖那些依赖于一些实例状态的可能性,这是必需的。

选项2级的要求更少概念行李(你已经知道self和方法,如绑定的功能,因为它是更普遍的情况)。但是你仍然可能更愿意明确地表明self没有被使用(并且口译员甚至可以通过一些优化来奖励你,而不必将功能部分地应用到self)。在这种情况下,您可以选择选项3并在功能上添加@staticmethod

相关问题