Python中的静态方法?

是否有可能在Python中有静态方法,所以我可以在不初始化类的情况下调用它们,如:

ClassName.StaticMethod ( ) 

是的,使用staticmethod装饰器

 class MyClass(object): @staticmethod def the_static_method(x): print x MyClass.the_static_method(2) # outputs 2 

请注意,一些代码可能会使用静态方法的旧方法,使用staticmethod作为函数而不是装饰器。 这应该只用于如果你必须支持Python的古代版本(2.2和2.3)

 class MyClass(object): def the_static_method(x): print x the_static_method = staticmethod(the_static_method) MyClass.the_static_method(2) # outputs 2 

这与第一个例子(使用@staticmethod )完全相同,只是没有使用好的装饰器语法

最后,谨慎使用staticmethod() 在Python中很less需要静态方法,而且在单独的“顶层”函数更清晰的情况下,我已经看到了很多情况。


以下是从文档逐字 ::

静态方法不会收到隐式的第一个参数。 为了声明一个静态方法,使用这个习惯用法:

 class C: @staticmethod def f(arg1, arg2, ...): ... 

@staticmethodforms是一个函数装饰器 – 详细信息请参阅函数定义中函数定义的描述。

它可以在类(如Cf() )或实例(如C().f() )上调用。 该实例被忽略,除了它的类。

Python中的静态方法类似于Java或C ++中的方法。 有关更高级的概念,请参见classmethod()

有关静态方法的更多信息,请参阅标准types层次结构中标准types层次结构的文档。

2.2版本中的新function

在版本2.4中更改:添加了函数装饰器语法。

我认为史蒂文其实是对的。 为了回答最初的问题,为了build立一个类方法,简单地假定第一个参数不会是一个调用实例,然后确保只调用该方法。

(请注意,这个答案是指Python 3.x.在Python 2.x中,你会得到一个TypeError来调用类本身的方法。)

例如:

 class Dog: count = 0 # this is a class variable dogs = [] # this is a class variable def __init__(self, name): self.name = name #self.name is an instance variable Dog.count += 1 Dog.dogs.append(name) def bark(self, n): # this is an instance method print("{} says: {}".format(self.name, "woof! " * n)) def rollCall(n): #this is implicitly a class method (see comments below) print("There are {} dogs.".format(Dog.count)) if n >= len(Dog.dogs) or n < 0: print("They are:") for dog in Dog.dogs: print(" {}".format(dog)) else: print("The dog indexed at {} is {}.".format(n, Dog.dogs[n])) fido = Dog("Fido") fido.bark(3) Dog.rollCall(-1) rex = Dog("Rex") Dog.rollCall(0) 

在这个代码中,“rollCall”方法假定第一个参数不是一个实例(就像它是由一个实例而不是一个类所调用的那样)。 只要从类而不是实例调用“rollCall”,代码就可以正常工作。 如果我们尝试从一个实例中调用“rollCall”,例如:

 rex.rollCall(-1) 

然而,它会引发exception,因为它会发送两个参数:自身和-1,而“rollCall”只被定义为接受一个参数。

顺便说一句,rex.rollCall()会发送正确数量的参数,但也会导致引发exception,因为现在当函数期望n是数字时,n将代表Dog实例(即rex)。

这是装饰进来的地方:如果我们在“rollCall”方法之前

 @staticmethod 

那么通过明确指出方法是静态的,我们甚至可以从一个实例中调用它。 现在,

 rex.rollCall(-1) 

会工作。 在方法定义之前插入@staticmethod,然后阻止实例将自己作为参数发送。

您可以通过尝试使用以下代码来validation此情况,而不使用@staticmethod行注释掉。

 class Dog: count = 0 # this is a class variable dogs = [] # this is a class variable def __init__(self, name): self.name = name #self.name is an instance variable Dog.count += 1 Dog.dogs.append(name) def bark(self, n): # this is an instance method print("{} says: {}".format(self.name, "woof! " * n)) @staticmethod def rollCall(n): print("There are {} dogs.".format(Dog.count)) if n >= len(Dog.dogs) or n < 0: print("They are:") for dog in Dog.dogs: print(" {}".format(dog)) else: print("The dog indexed at {} is {}.".format(n, Dog.dogs[n])) fido = Dog("Fido") fido.bark(3) Dog.rollCall(-1) rex = Dog("Rex") Dog.rollCall(0) rex.rollCall(-1) 

是的,请查看staticmethod装饰器:

 >>> class C: ... @staticmethod ... def hello(): ... print "Hello World" ... >>> C.hello() Hello World 

你并不需要使用@staticmethod装饰器。 只要声明一个方法(不期望自我参数),并从类中调用它。 装饰者只是在那里,如果你想能够从一个实例调用它(这不是你想要做的)

大多数情况下,你只是使用函数,但…

Python中的静态方法?

是否有可能在Python中有静态方法,所以我可以在不初始化类的情况下调用它们,如:

 ClassName.StaticMethod() 

是的,可以像这样创build静态方法(尽pipe使用下划线而不是CamelCase来实现方法更加Pythonic ):

 class ClassName(object): @staticmethod def static_method(kwarg1=None): '''return a value that is a function of kwarg1''' 

上面使用了装饰器语法。 这个语法相当于

 class ClassName(object): def static_method(kwarg1=None): '''return a value that is a function of kwarg1''' static_method = staticmethod(static_method) 

这可以像你所描述的那样使用:

 ClassName.static_method() 

一个静态方法的内置示例是Python 3中的str.maketrans() ,它是Python 2中string模块的一个函数。


另一个可以用于描述的选项是classmethod ,不同之处在于classmethod将类作为隐式的第一个参数来获得,如果是子类,那么它将把子类作为隐式的第一个参数。

 class ClassName(object): @classmethod def class_method(cls, kwarg1=None): '''return a value that is a function of the class and kwarg1''' 

请注意, cls不是第一个参数的必需名称,但是大多数有经验的Python编程人员会认为如果使用其他任何东西,这样做会很糟糕。

这些通常用作替代构造函数。

 new_instance = ClassName.class_method() 

一个内置的例子是dict.fromkeys()

 new_dict = dict.fromkeys(['key1', 'key2']) 

除了静态方法对象的特性之外,在组织模块级代码时,还可以使用某种美观方法。

 # garden.py def trim(a): pass def strip(a): pass def bunch(a, b): pass def _foo(foo): pass class powertools(object): """ Provides much regarded gardening power tools. """ @staticmethod def answer_to_the_ultimate_question_of_life_the_universe_and_everything(): return 42 @staticmethod def random(): return 13 @staticmethod def promise(): return True def _bar(baz, quux): pass class _Dice(object): pass class _6d(_Dice): pass class _12d(_Dice): pass class _Smarter: pass class _MagicalPonies: pass class _Samurai: pass class Foo(_6d, _Samurai): pass class Bar(_12d, _Smarter, _MagicalPonies): pass 

 # tests.py import unittest import garden class GardenTests(unittest.TestCase): pass class PowertoolsTests(unittest.TestCase): pass class FooTests(unittest.TestCase): pass class BarTests(unittest.TestCase): pass 

 # interactive.py from garden import trim, bunch, Foo f = trim(Foo()) bunch(f, Foo()) 

 # my_garden.py import garden from garden import powertools class _Cowboy(garden._Samurai): def hit(): return powertools.promise() and powertools.random() or 0 class Foo(_Cowboy, garden.Foo): pass 

现在,它变得更加直观和自我logging,在这种情况下,某些组件将被使用,理想地命名为不同的testing用例,以及直接testing模块如何映射到纯粹主义者testing的实际模块。

我经常发现应用这种方法来组织项目的实用程序代码是可行的。 通常情况下,人们会立即冲击并创build一个utils包,最终得到9个模块,其中一个具有120个LOC,其余的则是最多两个LOC。 我更喜欢从这开始,并将其转换为一个包,并创build模块只为真正值得他们的野兽:

 # utils.py class socket(object): @staticmethod def check_if_port_available(port): pass @staticmethod def get_free_port(port) pass class image(object): @staticmethod def to_rgb(image): pass @staticmethod def to_cmyk(image): pass 

也许最简单的select就是把这些function放在课外:

 class Dog(object): def __init__(self, name): self.name = name def bark(self): if self.name == "Doggy": return barking_sound() else: return "yip yip" def barking_sound(): return "woof woof" 

使用这种方法,修改或使用内部对象状态(有副作用)的函数可以保存在类中,可重用的实用函数可以移出。

假设这个文件叫做dogs.py 要使用这些,你可以叫dogs.barking_sound()而不是dogs.Dog.barking_sound

如果你真的需要一个静态方法来成为类的一部分,你可以使用staticmethod装饰器。