【问题标题】:Are there any benefits from using a @staticmethod?使用@staticmethod 有什么好处吗?
【发布时间】:2011-07-27 11:29:16
【问题描述】:

我想知道您是否在代码中使用 @staticmethod 装饰器。

我个人不使用它,因为写@staticmethod 比写self 需要更多的字母。

使用它的唯一好处(对我来说)可能是代码更清晰,但由于我通常为 sphinx 编写方法描述,所以我总是说明方法是否使用对象。

或者我应该开始使用@staticmethod 装饰器?

【问题讨论】:

  • 其实我还是一头雾水:python3中有哪些地方需要用到staticmethod?我发现很多地方都不需要使用staticmethod。

标签: python


【解决方案1】:

是否使用@staticmethod 取决于您要实现的目标。因为要输入更多内容而忽略装饰器是一个相当愚蠢的理由(无意冒犯!),并且表明您还没有理解 Python 中的 静态方法 的概念!

静态方法独立于类和任何类实例。他们只使用类范围作为命名空间。如果你省略了@staticmethod 装饰器,你正在创建一个实例方法,如果不构造实例就无法使用。

这是一个非常简单的类Foo

>>> class Foo(object):
...    @staticmethod
...    def foo():
...       print 'foo'
...
...    def bar(self):
...       print 'bar'

现在,Foo.foo() 是一个可以直接调用的静态方法:

>>> Foo.foo()
foo

另一方面,Foo.bar() 是一个实例方法,只能从Foo 的实例(对象)中调用:

>>> Foo.bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
>>> foo = Foo()
>>> foo.bar()
bar

回答您的问题:如果要定义静态方法,请使用@staticmethod。否则,不要。

如果你有一个不使用self的方法,因此可以写成一个静态方法,问问你自己:你是否想要在没有实例的情况下从外部访问这个函数?大多数时候,答案是:不。

【讨论】:

  • +1:“因为要输入更多内容而忽略装饰器是一个相当愚蠢的理由”。放下道歉。这很愚蠢。
  • 只是为了添加另一个使用 staticmethod 而不是 self 的原因 - 它不仅适用于 python,也适用于未来的维护者。它强调“此函数不依赖于类或实例的状态”,而不是 classmethod 或未修饰的方法。对于不熟悉代码的维护者(例如:5 年后的你),这可以更快地学习代码库。
  • 谢谢你的回答,现在当我看到这真的是一个愚蠢的理由:) 我还有很多东西要学,但是感谢你们学习不像以前那么痛苦.
  • 那为什么不在这个类中写一个单独的函数.....
【解决方案2】:

假设我们要在Math类中定义abs方法,那么我们有两种选择:

class Math():
    def abs(n):
        if n>0:
            return n
        else:
            return -n

class Math2():
    @staticmethod
    def abs(n):
        if n>0:
            return n
        else:
            return -n

在 Python2 中:

>>> Math.abs(-2)
TypeError: unbound method abs() must be called with Math instance as 
first argument (got int instance instead)

>>>Math().abs(-2)
TypeError: abs() takes exactly 1 argument (2 given)

>>> Math2.abs(-2)
2

>>> Math2().abs(-2)
2

python2 自动将Math().abs(-2) 当作Math().abs(self,-2),所以你必须使用@staticmethod

在 Python3 中

>>>Math.abs(-3)
3

>>>Math().abs(-3)
TypeError: abs() takes 1 positional argument but 2 were given

>>>Math2.abs(-3)
3

>>>Math2().abs(-3)
3

在python3中,你可以不使用静态方法使用classname.method(),但是当有人尝试使用instance.method()时会引发TypeError。

【讨论】:

  • 这个python2和python3的区别让我很困惑。
【解决方案3】:

@staticmethod 装饰器可以节省您的输入并提高可读性。

class Example:
    @staticmethod
    def some_method():
        return

等同于:

class Example:
    def some_method():
        return
    some_method = staticmethod(some_method)

我认为您可能会对 Python 中的静态方法感到困惑,因为该术语与其他语言不同。常规方法“绑定”到实例(self),类方法“绑定”到类(cls),而静态方法根本没有“绑定”(不能访问实例或类属性。

见:

【讨论】:

    【解决方案4】:

    除了前面的答案, 来自 pythons 文档 @staticmethod :

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

    class Test:
    
    @staticmethod
    def Foo():
        print('static Foo')
    
    def Bar():
        print('static Bar')
    
    
    Test.foo() # static Foo
    Test.bar() # static Bar
    
    obj = Test()
    obj.foo() # static Foo ; note that you can call it from class instance 
    obj.bar() # ERROR 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 2014-10-26
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2018-12-24
      • 2012-02-11
      相关资源
      最近更新 更多