Python中@staticmethod的意义是什么?

时间:2016-11-27 21:31:41

标签: 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()

此代码正常运行,不会返回任何错误。我的问题是:

  1. 我是否正确理解" self"可以理解为"这个方法将从一个实例调用"?

  2. 那么,@ staticmethod背后的逻辑是什么?是否可以创建可以从实例调用的静态方法?是不是是什么静态方法?

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

3 个答案:

答案 0 :(得分:4)

以下是static methods上的帖子。总结:

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

关于你的问题:

  1. 是。虽然变量名soundio-sys是约定,但它与实例有关。
  2. 静态方法可用于对同一类下的类似实用程序方法进行分组。
  3. 对于类中的方法,您需要添加self作为第一个参数,或者使用self修饰它的方法。 "非装饰方法"没有参数会引发错误。
  4. 通过参数调用时,可以更清楚地看到这些是如何工作的。一个修改过的例子:

    @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 作为第一个参数传递。
    • 同样,如果您需要访问类,请使用类方法。
    • 如果既不访问实例也不重视类,则可以使用静态方法。

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

    注意,有一种方法可以使用cls从实例方法访问类组件,从而避免了对类方法的需求:

    self.__class__

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

答案 1 :(得分:1)

以下是您问题的答案:

问题1:

  

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

没有。这不完全是Trueself表示函数的第一个参数应该是类的实例。例如:

def my_class_function(self)

可以称为:

self.my_class_function()
OR,
my_class_function(self)

此外,使用self作为类对象的引用并不是必需的。你可以使用任何东西(只要它是有效变量),但使用self是随处可见的标准。

问题2:

  

然后,@ staticmethod背后的逻辑是什么 - 创建可以从实例调用的静态方法?那不就是静态方法到底是什么意思吗?

@staticmethod变量与函数一起使用,在这些函数中,您不需要对函数中的类对象进行任何引用,即您没有使用self来访问任何类的属性或函数

问题3:

  

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

使用第二种方法,即使用@staticmetod,您可以使用类的对象从类外部调用函数,这与第三种方法不同(不使用装饰器),因为函数的范围在类中。

答案 2 :(得分:1)

方法对它们被调用的实例起作用。该实例作为第一个参数传递,通常称为self

类方法类似,但是对整个类对象而不是其中一个实例起作用。它们可以作为构造函数和工厂函数,或者用于配置设置以及同时影响类或其所有实例的其他情况,而不是单个实例。

第三个选项,静态方法,是奇怪的人。它们不传递实例或类。它们适用于在程序的类结构中嵌套实用程序功能以用于组织目的,但是以明确的方式(对代码审阅者,“linting”和程序检查工具等)表明您有意不依赖于实例或类值。这样,你就不会得到关于那个未使用的self的“变量声明但从未使用过”的警告。

从调用者的角度来看,静态方法看起来像任何其他方法调用。如果你没有@staticmethod可用,你可以使用普通的实例或类方法(尽管存在过多的风险“未使用的变量!!”linter warnings)。因此,与类方法不同,静态方法是Python的完全可选部分。他们没有为语言添加任何功能;相反,它们提供了一种方法,使开发人员的意图更加清晰。