在Python中使用静态方法的优点是什么?

我在代码中遇到了python的unbound方法错误

class Sample(object): '''This class defines various methods related to the sample''' def drawSample(samplesize,List): sample=random.sample(List,samplesize) return sample Choices=range(100) print Sample.drawSample(5,Choices) 

在阅读了许多有用的post之后,我想到了如何添加@staticmethod来获得代码的工作。 我是python新手。 有人可以请解释为什么要想定义静态方法? 或者,为什么不是所有的方法都被定义为静态方法?

静态方法的使用是有限的,因为他们没有权限访问类的实例的属性(就像普通的方法一样),并且他们没有权限访问类本身的属性(就像类方法一样)。

所以他们对日常的方法没有用处。

然而,将一些效用函数与一个类组合在一起可以是有用的,例如从一种types到另一种types的简单转换,除了提供的参数外(也可能是模块的全局属性),不需要访问任何信息。 )

他们可以放在课堂外,但是在课堂上分组可能是合理的。

您也可以通过实例或类引用方法,而不是模块名称,这可能有助于读者理解该方法与哪个实例相关。

请参阅这篇文章的详细解释。

TL; DR

它消除了self论证的使用。

2.减less内存使用量,因为Python不必为每个对象实例化一个绑定方法 :

 >>>RandomClass().regular_method is RandomClass().regular_method False >>>RandomClass().static_method is RandomClass().static_method True >>>RandomClass.static_method is RandomClass().static_method True 

3.提高了代码的可读性,表示该方法不依赖于对象本身的状态。

4.它允许方法重写,如果方法是在模块级定义的(即在类之外),子类将不能覆盖该方法。

这不是真正的问题,但是既然你已经说过你是一个Python新手,也许会有所帮助,而且没有其他人明确表示出来。

我永远不会通过使该方法成为静态方法来修复上述代码。 我要么放弃课程,只写一个函数:

 def drawSample(samplesize,List): sample=random.sample(List,samplesize) return sample Choices=range(100) print drawSample(5,Choices) 

如果你有很多相关的function,你可以将它们分组到一个模块中,也就是把它们放在同一个文件中,例如sample.py。 然后

 import sample Choices=range(100) print sample.drawSample(5,Choices) 

或者我会为这个类添加一个init方法,并创build一个有用方法的实例:

 class Sample(object): '''This class defines various methods related to the sample''' def __init__(self, thelist): self.list = thelist def draw_sample(self, samplesize): sample=random.sample(self.list,samplesize) return sample choices=Sample(range(100)) print choices.draw_sample(5) 

(我也在上面的例子中改变了案例惯例,以符合PEP 8推荐的风格。)

Python的优点之一是它并不强迫你为所有的东西使用类。 只有当数据或状态应该与方法关联时,才可以使用它们,这是类的用途。 否则,你可以使用函数,这是什么function。

当你从一个对象实例中调用一个函数对象时,它就成为一个“绑定方法”,并获取实例对象本身作为第一个参数传入。

当你在一个对象实例上调用一个classmethod对象(包装一个函数对象)时,实例对象的类将作为第一个参数传入。

当您调用staticmethod对象(包装函数对象)时,不会使用隐式的第一个参数。

 class Foo(object): def bar(*args): print args @classmethod def baaz(*args): print args @staticmethod def quux(*args): print args >>> foo = Foo() >>> Foo.bar(1,2,3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead) >>> Foo.baaz(1,2,3) (<class 'Foo'>, 1, 2, 3) >>> Foo.quux(1,2,3) (1, 2, 3) >>> foo.bar(1,2,3) (<Foo object at 0x1004a4510>, 1, 2, 3) >>> foo.baaz(1,2,3) (<class 'Foo'>, 1, 2, 3) >>> foo.quux(1,2,3) (1, 2, 3) 

为什么要定义静态方法

假设我们有一个叫Mathclass

没有人会想要创buildclass Math对象
然后调用像ceilfloorfabs这样的方法。

所以我们把它们变成static

比如做

 >> Math.floor(3.14) 

比…更好

 >> mymath = Math() >> mymath.floor(3.14) 

所以他们在某种程度上是有用的。 您不需要创build一个类的实例来使用它们。

为什么不是所有的方法都被定义为静态方法

他们不能访问实例variables。

 class Foo(object): def __init__(self): self.bar = 'bar' def too(self): print self.bar @staticmethod def foo(): print self.bar Foo().too() # works Foo.foo() # doesn't work 

这就是为什么我们不能使所有的方法都是静态的。

静态方法是伟大的,因为你不必声明该方法所属的对象的实例。

python的站点有一些关于静态方法的很好的文档:
http://docs.python.org/library/functions.html#staticmethod

静态方法在Python中几乎没有任何理由。 您可以使用实例方法或类方法。

 def method(self, args): self.member = something @classmethod def method(cls, args): cls.member = something @staticmethod def method(args): MyClass.member = something # The above isn't really working # if you have a subclass 

由于命名空间函数很好(正如之前指出的那样):

  1. 当我想要明确不改变对象状态的方法时,我使用静态方法。 这阻止了我的团队中的人们开始改变这些方法中的对象的属性。

  2. 当我重构真正烂的代码时,我开始尝试尽可能多地创build@staticmethod方法。 这使我可以将这些方法提取到一个类中 – 尽pipe我同意这一点,但这种方法很less用到,它确实有用了几次。