Python関数のパラメータのデフォルト値が可変オブジェクトの場合は注意が必要

WBOY
リリース: 2023-04-22 13:37:07
転載
1227 人が閲覧しました

フィボナッチ関数の再帰を高速化するために、変数オブジェクトが Python 関数のパラメータのデフォルト値に渡されているのを見ました。コードは次のとおりです:

def fib(n, cache={0: 0, 1: 1}):
if n not in cache:
cache[n] = fib(n - 1) + fib(n - 2)
return cache[n]
ログイン後にコピー

おかしくないですか?これができるということですか? 速度は本当に非常に速く、実行結果は次のとおりです:

小心此坑:Python 函数参数的默认值是可变对象

## ただし、これは行わないことをお勧めします。

小心此坑:Python 函数参数的默认值是可变对象

これは、すべてがオブジェクトであり、Python 関数もオブジェクトであるためです。パラメータのデフォルト値は、次の属性です。オブジェクト。パラメータのデフォルト値はコンパイル段階ですでに関数にバインドされています。変数オブジェクトの場合、Python 関数パラメータのデフォルト値は保存され、すべての呼び出し元で共有されます。つまり、関数パラメータのデフォルト値は、List や Dict などの変数オブジェクトであり、呼び出し元 A がそれを変更しました。その後、呼び出し元 B は、呼び出し時に A の変更結果を見ることになります。このようなモードでは、上記の fib アルゴリズムなど、予期しない結果が生じることがよくあります。しかし、それらのほとんどはバグです。

次の簡単なコードを見てみましょう:

def func(n, li = []):
for i in range(n):
li.append(i)
print(l)

func(2) # [0,1]
func(3,l=[1,2]) # [1,2,0,1,2]
func(2) # [0,1]
ログイン後にコピー

まず、このコードの出力を見積もることができます。コメント内の出力と同じであれば、間違っています。正しい結果は次のとおりです:

[0, 1]
[1, 2, 0, 1, 2]
[0, 1, 0, 1]
ログイン後にコピー

最後の func(2) がなぜこのようになっているか疑問に思うかもしれませんが、心配しないで、 print(id(li)) をデバッグしましょう:

def func(n, li = []):
print(id(li))
for i in range(n):
li.append(i)
print(li)

func(2)
func(3,li=[1,2])
func(2)
ログイン後にコピー

結果は次のとおりです。

140670243756736
[0, 1]
140670265684928
[1, 2, 0, 1, 2]
140670243756736
[0, 1, 0, 1]
ログイン後にコピー

最初の func(2) と 2 番目の func(2) の ID が同じであることに気づきましたか。これは、デフォルト値である同じ li を使用していることを示しています。これは変更可能なオブジェクトのロジックであり、すべての呼び出し元によって共有されます。

Python がこのように設計されている理由を詳しく知りたい場合は、http://cenalulu.github.io/python/default-mutable-arguments/

回避方法を参照してください。それ?

最善の方法は、可変オブジェクトを関数のデフォルト値として使用しないことです。この方法で使用する必要がある場合の解決策は次のとおりです:

def generate_new_list_with(my_list=None, element=None):
if my_list is None:
my_list = []
my_list.append(element)
return my_list
ログイン後にコピー
このように、my_list のデフォルト値が常に [] である場合。

最後に

#fib 関数の実装に感動するかもしれませんが、そのような使用法は非常に危険であり、独自のコードでは使用できないことに注意してください。

以上がPython関数のパラメータのデフォルト値が可変オブジェクトの場合は注意が必要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:51cto.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート