使用 @staticmethod 有什么好处吗?

13 投票
4 回答
4057 浏览
提问于 2025-04-16 22:21

我在想你们的代码里有没有用到 @staticmethod 这个装饰器。

就我个人来说,我不太用这个,因为写 @staticmethod 比写 self 要多打几个字。

用它的唯一好处(对我来说)可能就是让代码更清晰,但因为我通常会为方法写描述给 sphinx,所以我总是会说明这个方法是否使用了对象。

或者我是不是应该开始用 @staticmethod 这个装饰器呢?

4 个回答

0

@staticmethod 这个装饰器可以让你少打字,而且让代码看起来更清晰。

class Example:
    @staticmethod
    def some_method():
        return

这和下面的写法是一样的:

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

我觉得你可能对Python中的静态方法有些困惑,因为这个术语和其他语言不太一样。普通方法是“绑定”到实例上的(用 self 表示),类方法是“绑定”到类上的(用 cls 表示),而静态方法根本不“绑定”到任何东西(它不能访问实例或类的属性)。

你可以查看这些链接了解更多:

1

假设我们想在一个叫做 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)。

36

是否使用 @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,因此 可以 写成静态方法,那就问问自己:你是否希望在没有实例的情况下从外部访问这个函数?大多数情况下,答案是:不。

撰写回答