标签归档:static-methods

静态方法-如何从另一个方法调用一个方法?

问题:静态方法-如何从另一个方法调用一个方法?

当我有用于在类中调用另一个方法的常规方法时,我必须这样做

class test:
    def __init__(self):
        pass
    def dosomething(self):
        print "do something"
        self.dosomethingelse()
    def dosomethingelse(self):
        print "do something else"

但是当我有静态方法时,我不能写

self.dosomethingelse()

因为没有实例。在Python中如何从同一个类的另一个静态方法中调用一个静态方法,我该怎么做?

编辑:真是一团糟。好的,我将问题改回原来的问题。我已经有了彼得·汉森(Peter Hansen)评论中第二个问题的答案。如果您认为我应该再提出一个已经存在的答案的问题,请告诉我。

When I have regular methods for calling another method in a class, I have to do this

class test:
    def __init__(self):
        pass
    def dosomething(self):
        print "do something"
        self.dosomethingelse()
    def dosomethingelse(self):
        print "do something else"

but when I have static methods I can’t write

self.dosomethingelse()

because there is no instance. How do I have to do in Python for calling an static method from another static method of the same class?

Edit: what a mess. Ok, I edited back the question to the original question. I already have the answer to the second question that’s in Peter Hansen’s comment. If you think I should open another question for an answer I already have, plz tell me.


回答 0

class.method 应该管用。

class SomeClass:
  @classmethod
  def some_class_method(cls):
    pass

  @staticmethod
  def some_static_method():
    pass

SomeClass.some_class_method()
SomeClass.some_static_method()

class.method should work.

class SomeClass:
  @classmethod
  def some_class_method(cls):
    pass

  @staticmethod
  def some_static_method():
    pass

SomeClass.some_class_method()
SomeClass.some_static_method()

回答 1

在Python中如何从同一个类的另一个静态方法中调用一个静态方法,我该怎么做?

class Test() :
    @staticmethod
    def static_method_to_call()
        pass

    @staticmethod
    def another_static_method() :
        Test.static_method_to_call()

    @classmethod
    def another_class_method(cls) :
        cls.static_method_to_call()

How do I have to do in Python for calling an static method from another static method of the same class?

class Test() :
    @staticmethod
    def static_method_to_call()
        pass

    @staticmethod
    def another_static_method() :
        Test.static_method_to_call()

    @classmethod
    def another_class_method(cls) :
        cls.static_method_to_call()

回答 2

注意-看来问题已经改变了一些。关于如何从静态方法调用实例方法的问题的答案是,您不能不将实例作为参数传入或在静态方法中实例化该实例。

接下来的内容主要是回答“如何从另一个静态方法调用静态方法”:

请记住,Python中的静态方法和类方法之间有区别的。静态方法不使用隐式第一参数,而类方法则将类作为隐式第一参数(通常cls是按惯例)。考虑到这一点,这是您要执行的操作:

如果是静态方法:

test.dosomethingelse()

如果是类方法:

cls.dosomethingelse()

NOTE – it looks like the question has changed some. The answer to the question of how you call an instance method from a static method is that you can’t without passing an instance in as an argument or instantiating that instance inside the static method.

What follows is mostly to answer “how do you call a static method from another static method”:

Bear in mind that there is a difference between static methods and class methods in Python. A static method takes no implicit first argument, while a class method takes the class as the implicit first argument (usually cls by convention). With that in mind, here’s how you would do that:

If it’s a static method:

test.dosomethingelse()

If it’s a class method:

cls.dosomethingelse()

回答 3

好的,类方法和静态方法之间的主要区别是:

  • class方法具有自己的标识,这就是为什么必须在INSTANCE中调用它们的原因。
  • 另一方面,可以在多个实例之间共享静态方法,因此必须从CLASS中调用它

OK the main difference between class methods and static methods is:

  • class method has its own identity, that’s why they have to be called from within an INSTANCE.
  • on the other hand static method can be shared between multiple instances so that it must be called from within THE CLASS

回答 4

您不能从静态方法调用非静态方法,但是可以通过在静态方法内创建实例来实现。

class test2(object):
    def __init__(self):
        pass

    @staticmethod
    def dosomething():
        print "do something"
        #creating an instance to be able to call dosomethingelse(),or you may use any existing instace
        a=test2()
        a.dosomethingelse()

    def dosomethingelse(self):
        print "do something else"

test2.dosomething()

希望对您有帮助:)

you cant call non-static methods from static methods but by creating an instance inside the static method…. it should work like that

class test2(object):
    def __init__(self):
        pass

    @staticmethod
    def dosomething():
        print "do something"
        #creating an instance to be able to call dosomethingelse(),or you may use any existing instace
        a=test2()
        a.dosomethingelse()

    def dosomethingelse(self):
        print "do something else"

test2.dosomething()

hope that will help you :)


回答 5

如果这些不依赖于类或实例,那为什么不仅仅使它们成为一个函数呢?因为这似乎是显而易见的解决方案。当然,除非您认为它将需要被覆盖,子类化等等。如果是这样,那么前面的答案是最好的选择。我只是简单地提供一个可能满足或可能不适合某人需求的替代解决方案而感到沮丧;)。

因为正确的答案将取决于相关代码的用例;)享受

If these don’t depend on the class or instance then why not just make them a function? As this would seem like the obvious solution. Unless of course you think it’s going to need to be overwritten, subclass etc. If so then the previous answers are the best bet. Fingers crossed I wont get marked down for merely offering an alternative solution that may or may not fit someones needs ;).

As the correct answer will depend on the use case of the code in question ;) Enjoy


`staticmethod`和`abc.abstractmethod`:会融合吗?

问题:`staticmethod`和`abc.abstractmethod`:会融合吗?

在我的Python应用程序中,我想创建一个既是staticmethod和又是的方法abc.abstractmethod。我该怎么做呢?

我尝试同时应用两个装饰器,但不起作用。如果我这样做:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

我遇到异常*,如果执行此操作:

class C(object):
    __metaclass__ = abc.ABCMeta

    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

没有强制执行抽象方法。

如何制作抽象的静态方法?

*exceptions:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'

In my Python app I want to make a method that is both a staticmethod and an abc.abstractmethod. How do I do this?

I tried applying both decorators, but it doesn’t work. If I do this:

import abc

class C(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    @staticmethod    
    def my_function(): pass

I get an exception*, and if I do this:

class C(object):
    __metaclass__ = abc.ABCMeta

    @staticmethod    
    @abc.abstractmethod
    def my_function(): pass

The abstract method is not enforced.

How can I make an abstract static method?

*The exception:

File "c:\Python26\Lib\abc.py", line 29, in abstractmethod
 funcobj.__isabstractmethod__ = True
AttributeError: 'staticmethod' object has no attribute '__isabstractmethod__'

回答 0

class abstractstatic(staticmethod):
    __slots__ = ()
    def __init__(self, function):
        super(abstractstatic, self).__init__(function)
        function.__isabstractmethod__ = True
    __isabstractmethod__ = True

class A(object):
    __metaclass__ = abc.ABCMeta
    @abstractstatic
    def test():
        print 5
class abstractstatic(staticmethod):
    __slots__ = ()
    def __init__(self, function):
        super(abstractstatic, self).__init__(function)
        function.__isabstractmethod__ = True
    __isabstractmethod__ = True

class A(object):
    __metaclass__ = abc.ABCMeta
    @abstractstatic
    def test():
        print 5

回答 1

与开始的Python 3.3,它是可以组合 @staticmethod@abstractmethod,所以没有其他的建议是必要的了:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):

Starting with Python 3.3, it is possible to combine @staticmethod and @abstractmethod, so none of the other suggestions are necessary anymore:

@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):

回答 2

这样做:

  >>> import abc
  >>> abstractstaticmethod = abc.abstractmethod
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abstractstaticmethod
  ...     def themethod():
  ...          pass
  ... 
  >>> a = A()
  >>> Traceback (most recent call last):
  File "asm.py", line 16, in <module>
    a = A()
  TypeError: Can't instantiate abstract class A with abstract methods test

您输入“嗯?它只是重命名了@abstractmethod”,这是完全正确的。因为上述任何子类都必须包含@staticmethod装饰器。除了阅读代码时作为文档外,这里您不需要它。子类必须看起来像这样:

  >>> class B(A):
  ...     @staticmethod
  ...     def themethod():
  ...         print "Do whatevs"

要具有可以强制您将此方法设置为静态方法的函数,您必须将ABCmeta子类化以对其进行检查并强制执行。没有真正的回报,这是很多工作。(如果有人忘记了@staticmethod装饰器,无论如何他们都会得到一个明确的错误,只是不会提及静态方法。

因此,实际上它也一样有效:

  >>> import abc
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abc.abstractmethod
  ...     def themethod():
  ...         """Subclasses must implement this as a @staticmethod"""
  ...          pass

更新-另一种解释方式:

方法是静态的,它控制着它的调用方式。从不调用抽象方法。因此,除了出于文档目的之外,抽象静态方法是一个毫无意义的概念。

This will do it:

  >>> import abc
  >>> abstractstaticmethod = abc.abstractmethod
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abstractstaticmethod
  ...     def themethod():
  ...          pass
  ... 
  >>> a = A()
  >>> Traceback (most recent call last):
  File "asm.py", line 16, in <module>
    a = A()
  TypeError: Can't instantiate abstract class A with abstract methods test

You go “Eh? It just renames @abstractmethod”, and this is completely correct. Because any subclass of the above will have to include the @staticmethod decorator anyway. You have no need of it here, except as documentation when reading the code. A subclass would have to look like this:

  >>> class B(A):
  ...     @staticmethod
  ...     def themethod():
  ...         print "Do whatevs"

To have a function that would enforce you to make this method a static method you would have to subclass ABCmeta to check for that and enforce it. That’s a lot of work for no real return. (If somebody forgets the @staticmethod decorator they will get a clear error anyway, it just won’t mention static methods.

So in fact this works just as well:

  >>> import abc
  >>>
  >>> class A(object):
  ...     __metaclass__ = abc.ABCMeta
  ...     @abc.abstractmethod
  ...     def themethod():
  ...         """Subclasses must implement this as a @staticmethod"""
  ...          pass

Update – Another way to explain it:

That a method is static controls how it is called. An abstract method is never called. And abstract static method is therefore a pretty pointless concept, except for documentation purposes.


回答 3

目前在Python 2.X中这是不可能的,Python 2.X仅将方法强制为抽象或静态方法,而不会两者都强制执行。

在Python 3.2+中,添加了新的装饰器abc.abstractclassmethodabc.abstractstaticmethod以将其强制实施抽象和静态或抽象与类方法结合起来。

参见Python Issue 5867

This is currently not possible in Python 2.X, which will only enforce the method to be abstract or static, but not both.

In Python 3.2+, the new decoratorsabc.abstractclassmethod and abc.abstractstaticmethod were added to combine their enforcement of being abstract and static or abstract and a class method.

See Python Issue 5867


在类主体中调用类staticmethod?

问题:在类主体中调用类staticmethod?

当我尝试从类的主体中使用静态方法,并使用内置staticmethod函数作为装饰器来定义静态方法时,如下所示:

class Klass(object):

    @staticmethod  # use as decorator
    def _stat_func():
        return 42

    _ANS = _stat_func()  # call the staticmethod

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

我收到以下错误:

Traceback (most recent call last):<br>
  File "call_staticmethod.py", line 1, in <module>
    class Klass(object): 
  File "call_staticmethod.py", line 7, in Klass
    _ANS = _stat_func() 
  TypeError: 'staticmethod' object is not callable

我了解为什么会发生这种情况(描述符绑定),并且可以通过_stat_func()在上次使用后手动将其转换为静态方法来解决此问题,如下所示:

class Klass(object):

    def _stat_func():
        return 42

    _ANS = _stat_func()  # use the non-staticmethod version

    _stat_func = staticmethod(_stat_func)  # convert function to a static method

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

所以我的问题是:

是否有更好的方法(如更清洁或更“ Pythonic”的)来完成此任务?

When I attempt to use a static method from within the body of the class, and define the static method using the built-in staticmethod function as a decorator, like this:

class Klass(object):

    @staticmethod  # use as decorator
    def _stat_func():
        return 42

    _ANS = _stat_func()  # call the staticmethod

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

I get the following error:

Traceback (most recent call last):<br>
  File "call_staticmethod.py", line 1, in <module>
    class Klass(object): 
  File "call_staticmethod.py", line 7, in Klass
    _ANS = _stat_func() 
  TypeError: 'staticmethod' object is not callable

I understand why this is happening (descriptor binding), and can work around it by manually converting _stat_func() into a staticmethod after its last use, like so:

class Klass(object):

    def _stat_func():
        return 42

    _ANS = _stat_func()  # use the non-staticmethod version

    _stat_func = staticmethod(_stat_func)  # convert function to a static method

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

So my question is:

Are there better, as in cleaner or more “Pythonic”, ways to accomplish this?


回答 0

staticmethod对象显然具有__func__存储原始原始函数的属性(它们必须这样做)。所以这将工作:

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    _ANS = stat_func.__func__()  # call the staticmethod

    def method(self):
        ret = Klass.stat_func()
        return ret

顺便说一句,尽管我怀疑静态方法对象具有某种存储原始功能的属性,但我对具体细节一无所知。本着教别人钓鱼而不是给他们钓鱼的精神,这就是我所做的调查,并发现了这一点(Python会话中的C&P):

>>> class Foo(object):
...     @staticmethod
...     def foo():
...         return 3
...     global z
...     z = foo

>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>

在交互式会话中进行类似的挖掘(dir非常有帮助)通常可以非常快速地解决这些问题。

staticmethod objects apparently have a __func__ attribute storing the original raw function (makes sense that they had to). So this will work:

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    _ANS = stat_func.__func__()  # call the staticmethod

    def method(self):
        ret = Klass.stat_func()
        return ret

As an aside, though I suspected that a staticmethod object had some sort of attribute storing the original function, I had no idea of the specifics. In the spirit of teaching someone to fish rather than giving them a fish, this is what I did to investigate and find that out (a C&P from my Python session):

>>> class Foo(object):
...     @staticmethod
...     def foo():
...         return 3
...     global z
...     z = foo

>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>

Similar sorts of digging in an interactive session (dir is very helpful) can often solve these sorts of question very quickly.


回答 1

这是我更喜欢的方式:

class Klass(object):

    @staticmethod
    def stat_func():
        return 42

    _ANS = stat_func.__func__()

    def method(self):
        return self.__class__.stat_func() + self.__class__._ANS

Klass.stat_func由于DRY原理,我更喜欢这种解决方案。让我想起了Python 3中有新功能super()原因 :)

但是我与其他人一样,通常最好的选择是定义一个模块级别的功能。

例如带@staticmethod功能的递归可能看起来不太好(您需要通过调用Klass.stat_funcinside 来打破DRY原理Klass.stat_func)。那是因为您没有引用self内部静态方法。有了模块级功能,一切都会看起来不错。

This is the way I prefer:

class Klass(object):

    @staticmethod
    def stat_func():
        return 42

    _ANS = stat_func.__func__()

    def method(self):
        return self.__class__.stat_func() + self.__class__._ANS

I prefer this solution to Klass.stat_func, because of the DRY principle. Reminds me of the reason why there is a new super() in Python 3 :)

But I agree with the others, usually the best choice is to define a module level function.

For instance with @staticmethod function, the recursion might not look very good (You would need to break DRY principle by calling Klass.stat_func inside Klass.stat_func). That’s because you don’t have reference to self inside static method. With module level function, everything will look OK.


回答 2

在类定义之后注入class属性怎么办?

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    def method(self):
        ret = Klass.stat_func()
        return ret

Klass._ANS = Klass.stat_func()  # inject the class attribute with static method value

What about injecting the class attribute after the class definition?

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    def method(self):
        ret = Klass.stat_func()
        return ret

Klass._ANS = Klass.stat_func()  # inject the class attribute with static method value

回答 3

这是由于staticmethod是描述符,并且需要获取类级别的属性才能执行描述符协议并获得真正的可调用对象。

从源代码:

可以在类(例如C.f())或实例(例如C().f())上调用它;该实例除其类外均被忽略。

但是在定义类时,不能直接从类内部进行。

但是正如一位评论者所提到的,这根本不是一个真正的“ Pythonic”设计。只需使用模块级功能即可。

This is due to staticmethod being a descriptor and requires a class-level attribute fetch to exercise the descriptor protocol and get the true callable.

From the source code:

It can be called either on the class (e.g. C.f()) or on an instance (e.g. C().f()); the instance is ignored except for its class.

But not directly from inside the class while it is being defined.

But as one commenter mentioned, this is not really a “Pythonic” design at all. Just use a module level function instead.


回答 4

那这个解决方案呢?它不依赖@staticmethod装饰器实现的知识。内部类StaticMethod充当静态初始化函数的容器。

class Klass(object):

    class StaticMethod:
        @staticmethod  # use as decorator
        def _stat_func():
            return 42

    _ANS = StaticMethod._stat_func()  # call the staticmethod

    def method(self):
        ret = self.StaticMethod._stat_func() + Klass._ANS
        return ret

What about this solution? It does not rely on knowledge of @staticmethod decorator implementation. Inner class StaticMethod plays as a container of static initialization functions.

class Klass(object):

    class StaticMethod:
        @staticmethod  # use as decorator
        def _stat_func():
            return 42

    _ANS = StaticMethod._stat_func()  # call the staticmethod

    def method(self):
        ret = self.StaticMethod._stat_func() + Klass._ANS
        return ret

Python中的静态方法?

问题:Python中的静态方法?

Python中是否可以有无需初始化类即可调用的静态方法,例如:

ClassName.static_method()

Is it possible to have static methods in Python which I could call without initializing a class, like:

ClassName.static_method()

回答 0

是的,使用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中需要使用静态方法,而我已经看到它们使用了很多次,而使用单独的“顶层”函数会更加清楚。


以下是文档的逐字记录

静态方法不会收到隐式的第一个参数。要声明静态方法,请使用以下惯用法:

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

@staticmethod形式是一个函数装饰器 –有关详细信息,请参见函数定义中的函数定义描述。

可以在类(如C.f())或实例(如C().f())上调用它。该实例除其类外均被忽略。

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

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

2.2版中的新功能。

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

Yep, using the staticmethod decorator

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print(x)

MyClass.the_static_method(2)  # outputs 2

Note that some code might use the old method of defining a static method, using staticmethod as a function rather than a decorator. This should only be used if you have to support ancient versions of Python (2.2 and 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

This is entirely identical to the first example (using @staticmethod), just not using the nice decorator syntax

Finally, use staticmethod() sparingly! There are very few situations where static-methods are necessary in Python, and I’ve seen them used many times where a separate “top-level” function would have been clearer.


The following is verbatim from the documentation::

A static method does not receive an implicit first argument. To declare a static method, use this idiom:

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

The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod().

For more information on static methods, consult the documentation on the standard type hierarchy in The standard type hierarchy.

New in version 2.2.

Changed in version 2.4: Function decorator syntax added.


回答 1

我认为史蒂文实际上是对的。为了回答最初的问题,然后,为了建立一个类方法,只需假设第一个参数不会成为调用实例,然后确保仅从类中调用该方法即可。

(请注意,此答案是针对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)

但是,它将引发异常,因为它将发送两个参数:本身和-1,并且“ rollCall”仅定义为接受一个参数。

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

这就是装饰的来源:如果我们在“ rollCall”方法之前加上

@staticmethod

然后,通过明确声明该方法是静态的,我们甚至可以从实例中调用它。现在,

rex.rollCall(-1)

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

您可以通过尝试以下代码(带有和不带有@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)

I think that Steven is actually right. To answer the original question, then, in order to set up a class method, simply assume that the first argument is not going to be a calling instance, and then make sure that you only call the method from the class.

(Note that this answer refers to Python 3.x. In Python 2.x you’ll get a TypeError for calling the method on the class itself.)

For example:

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)

In this code, the “rollCall” method assumes that the first argument is not an instance (as it would be if it were called by an instance instead of a class). As long as “rollCall” is called from the class rather than an instance, the code will work fine. If we try to call “rollCall” from an instance, e.g.:

rex.rollCall(-1)

however, it would cause an exception to be raised because it would send two arguments: itself and -1, and “rollCall” is only defined to accept one argument.

Incidentally, rex.rollCall() would send the correct number of arguments, but would also cause an exception to be raised because now n would be representing a Dog instance (i.e., rex) when the function expects n to be numerical.

This is where the decoration comes in: If we precede the “rollCall” method with

@staticmethod

then, by explicitly stating that the method is static, we can even call it from an instance. Now,

rex.rollCall(-1)

would work. The insertion of @staticmethod before a method definition, then, stops an instance from sending itself as an argument.

You can verify this by trying the following code with and without the @staticmethod line commented out.

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)

回答 2

是的,请检查staticmethod装饰器:

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

Yes, check out the staticmethod decorator:

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

回答 3

您真的不需要使用 @staticmethod装饰器。只需声明一个方法(不需要self参数)并从类中调用它即可。装饰器仅在您还希望能够从实例调用它的情况下存在(这不是您想要执行的操作)

通常,您只是使用函数而已…

You don’t really need to use the @staticmethod decorator. Just declaring a method (that doesn’t expect the self parameter) and call it from the class. The decorator is only there in case you want to be able to call it from an instance as well (which was not what you wanted to do)

Mostly, you just use functions though…


回答 4

Python中的静态方法?

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

ClassName.StaticMethod()

是的,可以这样创建静态方法(尽管使用下划线代替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()

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


您可以使用的另一个选择是classmethod,不同之处是class方法将类作为隐式第一个参数获取,如果将其继承,则将子类作为隐式第一个参数获取。

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'])

Static methods in Python?

Is it possible to have static methods in Python so I can call them without initializing a class, like:

ClassName.StaticMethod()

Yes, static methods can be created like this (although it’s a bit more Pythonic to use underscores instead of CamelCase for methods):

class ClassName(object):

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

The above uses the decorator syntax. This syntax is equivalent to

class ClassName(object):

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

    static_method = staticmethod(static_method)

This can be used just as you described:

ClassName.static_method()

A builtin example of a static method is str.maketrans() in Python 3, which was a function in the string module in Python 2.


Another option that can be used as you describe is the classmethod, the difference is that the classmethod gets the class as an implicit first argument, and if subclassed, then it gets the subclass as the implicit first argument.

class ClassName(object):

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

Note that cls is not a required name for the first argument, but most experienced Python coders will consider it badly done if you use anything else.

These are typically used as alternative constructors.

new_instance = ClassName.class_method()

A builtin example is dict.fromkeys():

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

回答 5

除了静态方法对象的行为方式的特殊性之外,在组织模块级代码时,还可以利用它们带来某种美感。

# 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

现在,它变得更加直观和具有自文档说明性,在这种情况下,应使用某些组件,并且它非常适合命名不同的测试用例,并具有一种简单的方法来将测试模块映射到测试对象中的实际模块以供纯粹主义者使用。

我经常发现将这种方法应用于组织项目的实用程序代码是可行的。人们经常会立即赶紧创建一个utils包装,最终得到9个模块,其中一个模块具有120个LOC,其余模块最多为两个十几个LOC。我更喜欢从此开始并将其转换为包,并仅为真正应得的野兽创建模块:

# 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

Aside from the particularities of how static method objects behave, there is a certain kind of beauty you can strike with them when it comes to organizing your module-level code.

# 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

It now becomes a bit more intuitive and self-documenting in which context certain components are meant to be used and it pans out ideally for naming distinct test cases as well as having a straightforward approach to how test modules map to actual modules under tests for purists.

I frequently find it viable to apply this approach to organizing a project’s utility code. Quite often, people immediately rush and create a utils package and end up with 9 modules of which one has 120 LOC and the rest are two dozen LOC at best. I prefer to start with this and convert it to a package and create modules only for the beasts that truly deserve them:

# 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

回答 6

也许最简单的选择就是将这些函数放在类之外:

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装饰器。

Perhaps the simplest option is just to put those functions outside of the class:

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"

Using this method, functions which modify or use internal object state (have side effects) can be kept in the class, and the reusable utility functions can be moved outside.

Let’s say this file is called dogs.py. To use these, you’d call dogs.barking_sound() instead of dogs.Dog.barking_sound.

If you really need a static method to be part of the class, you can use the staticmethod decorator.


回答 7

因此,静态方法是可以在不创建类对象的情况下调用的方法。例如 :-

    @staticmethod
    def add(a, b):
        return a + b

b = A.add(12,12)
print b

在上面的示例中,方法add是通过类名A而不是对象名来调用的。

So, static methods are the methods which can be called without creating the object of a class. For Example :-

    @staticmethod
    def add(a, b):
        return a + b

b = A.add(12,12)
print b

In the above example method add is called by the class name A not the object name.


回答 8

Python静态方法可以通过两种方式创建。

  1. 使用staticmethod()

    class Arithmetic:
        def add(x, y):
            return x + y
    # create add static method
    Arithmetic.add = staticmethod(Arithmetic.add)
    
    print('Result:', Arithmetic.add(15, 10))

输出:

结果:25

  1. 使用@staticmethod

    class Arithmetic:
    
    # create add static method
    @staticmethod
    def add(x, y):
        return x + y
    
    print('Result:', Arithmetic.add(15, 10))

输出:

结果:25

Python Static methods can be created in two ways.

  1. Using staticmethod()

    class Arithmetic:
        def add(x, y):
            return x + y
    # create add static method
    Arithmetic.add = staticmethod(Arithmetic.add)
    
    print('Result:', Arithmetic.add(15, 10))
    

Output:

Result: 25

  1. Using @staticmethod

    class Arithmetic:
    
    # create add static method
    @staticmethod
    def add(x, y):
        return x + y
    
    print('Result:', Arithmetic.add(15, 10))
    

Output:

Result: 25


回答 9

我不时遇到这个问题。我喜欢的用例和示例是:

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

创建cmath类的对象没有任何意义,因为cmath对象中没有任何状态。但是,cmath是所有以某种方式相关的方法的集合。在上面的示例中,cmath中的所有函数都以某种方式作用于复数。

I encounter this question from time to time. The use case and example that I am fond of is:

jeffs@jeffs-desktop:/home/jeffs  $ python36
Python 3.6.1 (default, Sep  7 2017, 16:36:03) 
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>> 

It does not make sense to create an object of class cmath, because there is no state in a cmath object. However, cmath is a collection of methods that are all related in some way. In my example above, all of the functions in cmath act on complex numbers in some way.