13

我对 Python 中的函数调用有疑问。假设我想编写一个名为 superLongFunc(expr) 的函数。该函数超长且很难调试。我想将函数拆分为更小的辅助函数以获得更好的可读性,例如 smallFunc1(expr)、smallFunc2(expr) 等。

我的问题是,这会影响代码的性能吗?调用函数在 Python 中究竟是如何工作的?Python 是否通过引用将变量传递给函数?还是在将变量提供给函数之前复制变量?

我知道这是一个非常愚蠢的问题,但它一直困扰着我一段时间。提前致谢!

4

1 回答 1

16

Python 使用有时称为call-by-object的系统。将参数传递给函数时不会复制任何内容。函数参数的名称在函数体内本地绑定到函数调用中提供的相同对象。

这与大多数人认为的“按值调用”不同,因为它不会复制对象。但它也不同于“通过引用调用”,因为引用是对对象的——绑定了一个新名称,但对同一个对象。这意味着您可以改变传入的对象,但在函数内部重新绑定名称对函数外部没有影响。一个简单的区别示例:

>>> def func(x):
...     x[0] = 2 # Mutating the object affects the object outside the function
>>> myList = [1]
>>> func(myList)
>>> myList # myList has changed
[2]
>>> def func(x):
...     x = 2 # rebinding name has no effect outside the function
>>> myList = [1]
>>> func(myList)
>>> myList # myList is unaffected
[1]

我的简单思考方式是,对裸名称的赋值——即形式的语句name = value——与 Python 中的其他所有内容完全不同。对名称而不是值进行操作的唯一name = value方法是 do 。(这有一些挑剔的例外,比如乱搞globals()等等,但无论如何这些都是危险的领域。)特别name = value不同于obj.prop = value, obj[0] = value,obj += value和其他看起来像赋值但实际上对对象而不是名称进行操作的类似事物。

也就是说,Python 中的函数调用本身就有一定的开销(用于设置执行框架等)。如果一个函数被多次调用,这种开销会导致明显的性能影响。因此,将一个函数拆分为多个仍然会对性能产生影响,因为每个额外的函数调用都会增加一些开销。

于 2012-07-20T19:31:56.593 回答