在函数中使用静态方法代替子函数的必要性

Necessity of using static methods instead of sub-functions in a function

我看过关于 difference between @classmethod and @staticmethod and about that between @staticmethod and global functions 的讨论,但我仍然对 @staticmethod 和函数中的子函数之间的区别感到困惑。

考虑下面这个例子(修改自The definitive guide on how to use static, class or abstract methods in Python):

class Pizza(object):
    def __init__(self, cheese, vegetables):
        self.cheese = cheese
        self.vegetables = vegetables

    @staticmethod
    def mix_ingredients(x, y):
        return x + y

    def cook(self):
        return self.mix_ingredients(self.cheese, self.vegetables)

为什么不呢:

def cook_pizza(cheese, vegetables):
    def mix_ingredients(x, y):
        return x + y
    return mix_ingredients(cheese, vegetables)

在这个例子中,我曾经使用过的函数是 cook in Pizza。假设将来我不会在 Pizza 中定义任何其他功能,即我只做比萨饼烹饪。我不能简单地将其定义为一个函数 cook_pizza 吗?这样 mix_ingredients 就不会是全局的,也不会与其他实例发生名称冲突。

在这种情况下写成 @staticmethod 有什么优点或缺点吗?比如Pizza(cheese, vegetables).cook()是否比cook_pizza(cheese, vegetables)性能更好,因为前者在过程中不需要每次都定义mix_ingredients

基本区别在于您可以使用使用 staticmethod 修饰的函数而无需实例化 class,

但是如果你创建一个 sub-function/inner-function 你就不能从定义它的外部函数访问它。

方法

没有实例化:

In [2]: Pizza.cook()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-4a252d4e9619> in <module>()
----> 1 Pizza.cook()

TypeError: cook() missing 1 required positional argument: 'self'

实例:

In [4]: Pizza('cheese', 'vegetables').cook()
Out[4]: 'cheesevegetables'

静态方法

没有实例化:

In [5]: Pizza.mix_ingredients(1,2)
Out[5]: 3

性能:

每次调用cook_pizza都会定义嵌套函数,对执行时间有影响

import timeit

def method():
    return 'method'

def method_with_inner():
    def inner():
        return 'inner'
    return inner()

执行

 print(timeit.timeit("method()", setup="from __main__ import method"))

0.0910306089790538

print(timeit.timeit("method_with_inner()", setup="from __main__ import method_with_inner"))

0.24090809898916632

旁注

cook_pizza 可能是一个静态方法,因为它不使用在 class 级别定义的任何变量或自身的存储。

感谢:@Shadow @abarnert 在此答案的讨论线程中做出的贡献。