Python中@staticmethod的意义是什么?

rbr*_*rtk 5 python static-methods

我开发了这个简短的测试/示例代码,以更好地了解静态方法在Python中的工作方式。

class TestClass:
    def __init__(self, size):
        self.size = size

    def instance(self):
        print("regular instance method - with 'self'")

    @staticmethod
    def static():
        print("static instance method - with @staticmethod")

    def static_class():
        print("static class method")


a = TestClass(1000)

a.instance()
a.static()
TestClass.static_class()
Run Code Online (Sandbox Code Playgroud)

该代码正常工作,不会返回任何错误。我的问题是:

  1. 我是否正确理解“自我”可以理解为类似于“将从实例中调用此方法”?

  2. 再说一遍,@ staticmethod背后的逻辑是什么?是否可以创建可以从实例调用的静态方法?不就是没有什么静态方法是什么?

  3. 为什么第二种方法比第三种方法更受青睐?(我假设装饰器存在,所以有一点要注意。)第三个选项似乎更简单,直接。

pyl*_*ang 5

这是一篇关于静态方法的帖子。总之:

  • 实例方法:需要实例作为第一个参数
  • 类方法:要求类作为第一个参数
  • 静态方法:不需要作为第一个参数

关于您的问题:

  1. 是的。虽然变量名self是一个约定,但它与实例有关。
  2. 静态方法可用于将类似的实用程序方法分组到同一类下。
  3. 对于类中的方法,您需要将其添加self为第一个参数或使用@staticmethod. 没有参数的“非装饰方法”将引发错误。

当使用参数调用时,看看这些是如何工作的可能会更清楚。修改后的例子:

class TestClass:

    weight = 200                             # class attr 

    def __init__(self, size):
        self.size = size                     # instance attr

    def instance_mthd(self, val):
        print("Instance method, with 'self':", self.size*val)

    @classmethod
    def class_mthd(cls, val):
        print("Class method, with `cls`:", cls.weight*val)

    @staticmethod
    def static_mthd(val):
        print("Static method, with neither args:", val)

a = TestClass(1000)

a.instance_mthd(2)
# Instance method, with 'self': 2000

TestClass.class_mthd(2)
# Class method, with `cls`: 400

a.static_mthd(2)
# Static method, with neither args: 2
Run Code Online (Sandbox Code Playgroud)

总的来说,您可以从访问的角度考虑每种方法:

  • 如果您需要访问实例或实例组件(例如实例属性),请使用实例方法,因为它self作为第一个参数传递。
  • 同样,如果您需要访问一个类,请使用类方法。
  • 如果对实例和类的访问都不重要,则可以使用静态方法。

请注意,在上面的示例中,为每个方法类型传递了相同的参数,但对实例和类属性的访问分别通过self和不同cls

请注意,有一种方法可以通过 using 从实例方法访问类组件self.__class__,从而无需使用类方法:

    ...

    def instance_mthd2(self, val):
        print("Instance method, with class access via `self`:", self.__class__.weight*val)
    ...

a.instance_mthd2(2)
# Instance method, with class access via `self`: 400
Run Code Online (Sandbox Code Playgroud)

REF:我建议观看 Raymond Hettinger 的演讲 Python 的类开发工具包,其中通过示例清楚地阐明了每种方法类型的用途。