yiskw note

機械学習やプログラミングについて気まぐれで書きます

【Python】不要な変数や返り値にアンダースコア(_)を使用する際の注意点


Pythonでは,不要な関数の返り値やを無視する方法として,アンダースコア(_)を使用する方法があります.
例えば以下のような例です.

for _ in range(10):
    print("Hello")

このようにforループの際に使用しない値をアンダースコア(_)とすることで,
その値を使用しないということを示すことができます.

自分はよくこの書き方していて,「不要な値をアンダースコアに渡すことで,メモリを占有せずに値を破棄できる」と思っておりました.
しかしながら,実際にはこれは間違いだったということを最近知りました. 正しい理解は以下の通りです.

  1. アンダースコア(_)は,変数名の一つ
  2. 不要な変数や返り値を割り当てるのに,慣習的に用いられている
  3. メモリを占有しないということはなく,破棄するにはdelする必要がある

つまり「不要な値をアンダースコアに渡すことで,メモリを占有せずに値を破棄できる」というのは大きな間違いで,
ちゃんとメモリを占有する変数で,慣例的に不要なものをアンダースコア(_)に割り当てているだけ,ということです.

こちらに関して実際に確認してみます.
まずアンダースコア(_)に値を割り当てて,変数名の一覧を確認したいと思います.

 python
Python 3.9.1 (default, Jun 20 2021, 10:59:30) 
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
>>> _ = "hoge"
>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '_': 'hoge'}
>>> 

確かに_という変数に"hoge"という値が割り当てられているのがわかります.
ちなみにちゃんとメモリも占有しております.

 python
Python 3.9.1 (default, Jun 20 2021, 10:59:30) 
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> _ = "hoge"
>>> _.__sizeof__()
53

メモリを破棄するには,delを使用します.

 python
Python 3.9.1 (default, Jun 20 2021, 10:59:30) 
[Clang 12.0.5 (clang-1205.0.22.9)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> _ = "hoge"
>>> del _
>>> _.__sizeof__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_' is not defined

今回のように小さい文字列だけであれば,大してメモリも占有しないので大きな問題にはなりませんが,
深層学習などでGPUに載せたテンソルをアンダースコア(_)に割り当てたままにしてしまい,
メモリを占有しっぱなしということもありそうなので,注意が必要です.

Reference

What is the purpose of the single underscore "_" variable in Python? - Stack Overflow