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 = valuePython の他のすべてのものとはまったく異なるということです。値ではなく名前を操作する唯一の方法は、 do を実行することですname = value。(これには、いじくり回すなどの細かい例外がありますが、globals()とにかく危険な領域です。) 特に、 、、、および代入のように見えるが実際には名前ではなくオブジェクトを操作する他の同様のものとname = valueは異なります。obj.prop = valueobj[0] = valueobj += value

とはいえ、Python での関数呼び出しには、それ自体にある程度のオーバーヘッドがあります (実行フレームの設定など)。関数が何度も呼び出されると、このオーバーヘッドがパフォーマンスに顕著な影響を与える可能性があります。そのため、1 つの関数を複数に分割しても、追加の関数呼び出しごとにオーバーヘッドが追加されるため、パフォーマンスに影響を与える可能性があります。

于 2012-07-20T19:31:56.593 に答える