【问题标题】:Why use staticmethod instead of no decorator at all为什么使用静态方法而不是完全不使用装饰器
【发布时间】:2013-02-25 09:12:26
【问题描述】:

关于 SO 有几个很好的解释,说明为什么/何时应该使用类方法与静态方法,但我无法找到关于何时使用静态方法而不是完全不修饰的答案。考虑一下这个

class Foo(object):        
    @staticmethod
    def f_static(x):
        print("static version of f, x={0}".format(x))

    def f_standalone(x):
        print("standalone verion of f, x={0}".format(x))

还有一些输出:

>>> F = Foo
>>> f = F()
>>> F.f_static(5)
static version of f, x=5
>>> F.f_standalone(5)
standalone verion of f, x=5
>>> f.f_static(5)
static version of f, x=5
>>> f.f_standalone(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f_standalone() takes 1 positional argument but 2 were given

从我在这里读到的内容来看,使用 staticmethod 的主要原因基本上是将概念上相似的东西放在一起。从上面的示例中,似乎两种解决方案都可以做到这一点。唯一的缺点是您似乎无法从实例调用非静态方法。也许我太习惯其他编程语言了,但这并没有让我很困扰;我可以从 Python 中的实例调用类级别的东西总是令人惊讶。

那么,这基本上是两者之间的唯一区别吗?还是我错过了其他好处?谢谢

【问题讨论】:

  • “唯一的缺点是您似乎无法从实例中调用非静态方法”——因此,很明显,您已经找到了装饰器存在的原因。这是为了使静态方法的行为与其他语言中的行为一样。 (以及帮助传达该方法的调用方式。)仅仅因为它对您没有好处并不意味着它不是一个有效的理由。
  • "这是为了让静态方法的行为与其他语言中的行为一样"。您不能从 Java 中的实例调用静态方法。 Objective-C 本身没有这种意义上的静态方法,但是你不能从 obj-c 实例调用类方法。
  • 在 Java 中,您当然可以通过实例调用静态方法:ideone.com/Gslfp0(也就是说,从语法上讲,我相信编译器仍然只是将其解析为对类型为的静态方法的调用说变量,但懒得测试。)我认为这是 Python 所追求的“静态”方法和“类”方法之间的主要区别。
  • 另外,从个人角度来说,如果我看到像你在f_standalone() 上使用的签名,我首先想到的不是“哦,那一定是类方法”,而是“为什么他是在使用x 而不是self?!”。
  • 不是真的,我只是假设这些知识。 (这就是我所说的“它使静态方法的行为与其他语言一样”的意思——无论是通过类还是实例,调用都能正常工作。)

标签: python oop function static-methods


【解决方案1】:

您似乎使用的是 python 3。在 python 2 中:

In [1]: class Foo(object):
   ...:     def f_standalone(x):
   ...:         print("standalone version of f, x={}".format(x))
   ...:

In [2]: Foo.f_standalone(12)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-2d315c006153> in <module>()
----> 1 Foo.f_standalone(12)

TypeError: unbound method f_standalone() must be called with Foo instance as first argument (got int instance instead)

在 python 3 中,你错过了另一个奇怪的用例:

In [1]: class Foo(object):
   ...:     def f_standalone(x):
   ...:         print("standalone version of f, x={}".format(x))
   ...:     @staticmethod
   ...:     def f_static(x):
   ...:         print("static version of f, x={}".format(x))
   ...:

In [2]: Foo().f_standalone()
standalone version of f, x=<__main__.Foo object at 0x1064daa10>

In [3]: Foo().f_static()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-addf9c3f2477> in <module>()
----> 1 Foo().f_static()

TypeError: f_static() missing 1 required positional argument: 'x'

【讨论】:

    猜你喜欢
    • 2018-10-27
    • 2016-02-17
    • 2011-02-15
    • 2010-09-17
    • 2010-12-31
    • 1970-01-01
    • 2011-12-11
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多