LoginSignup
3
1

More than 1 year has passed since last update.

うぉ!Pythonで引数のデフォルト値をミュータブルな型にした結果

Last updated at Posted at 2021-12-24

Pythonで初心者ネタを投稿します。
タイトル見てニヤニヤしながら結果を予想して来た皆様、ご想像の通りなのでそっと閉じてください。

Pythonにはミュータブル(変更可能)な型と、イミュータブル(変更不能)な型があります。
bool、int、float、strなどは、イミュータブルな型。
list、dict、setなどはミュータブルな型です。

以下のように、Pythonの引数にデフォルト値を指定したとします。
ショッピングカートの配列に商品を入れる関数です。
デフォルト値には空の配列、つまりミュータブルな型の値を指定しました。

def add_to_cart(product: str, *, cart: list = []) -> list:
    cart.append(product)
    return cart


taro_shopping_cart = add_to_cart("Playstation5")
print(f"太郎さんのカート :{taro_shopping_cart}")

hanako_shopping_cart = add_to_cart("みかん")
print(f"花子さんのカート :{hanako_shopping_cart}")

太郎さんはプレステ5をカートに入れ、花子さんはみかんをカートに入れました。
自然ですよね。
この関数を使った結果はどのようになるでしょう。

太郎さんのカート :['Playstation5']
花子さんのカート :['Playstation5', 'みかん']

花子さんのカートにプレステ5が入ってしまいました。
ワンクリックで決済してたら、卒倒しますね。

Pythonでは、引数のデフォルト値が評価されるのは、関数が定義された時だけです。
なので最初の定義でcartに空の配列が入ってからは、その空の配列がずっと使いまわされます。

解消方法としては、単純でデフォルト値にミュータブルな値を設定しないことです。
ここではNoneを指定しました。

def add_to_cart(product: str, *, cart: list = None) -> list:
    if cart is None:
        cart = []
    cart.append(product)
    return cart


taro_shopping_cart = add_to_cart("Playstation5")
print(f"太郎さんのカート :{taro_shopping_cart}")

hanako_shopping_cart = add_to_cart("みかん")
print(f"花子さんのカート :{hanako_shopping_cart}")

実行結果

太郎さんのカート :['Playstation5']
花子さんのカート :['みかん']

理由は知っている人にとっては当たり前のことですし、PyCharm先生もちゃんとハイライトして"Default argument value is mutable"って注意してくれるので、ハマる人はたぶんいないと思います。

ただただ、adventカレンダーにちょっと参加したかっただけです。
そしてまだこれを知らなかった人が検索してこの記事を読んで理解してもらえたら嬉しいです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1