はじめに
ご存知のようにPythonはその書きやすさからプログラミング初心者にも敷居の低い言語として親しまれており、「初めて触れる言語がPython」という方も少なくありません。
しかしそんなPythonにもやってはいけないアンチパターン(禁じ手)があり、初心者が知らずに踏んでしまうと対処に苦しむ事になってしまいます。
そこで、Pythonのアンチパターンのうち、特に初心者が注意すべき**「変数の命名」の中でも特に致命的な同名変数定義による代入**についてご紹介させていただこうと思います。
悪い例
下のコードは、タプル型変数tuple
の中身をリスト型に変換して、リスト型変数list
と結合させるものです。
一見至って普通のデータ操作ですが、これ実は動きません。エラーが出ます。
>>> list = ["Apple", "Orange", "Grape"]
>>> tuple = ("Peach", "Strawberry")
>>> list.append(list(tuple))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable
何がまずかった?
原因は1行目にあります。
全体として、Pythonにはlist()
という標準組み込み関数があり、これで引数に与えたIterableなオブジェクトをリスト型に変換することができます。
3行目のappend()
の中身list(tuple)
ではこの関数を呼び出そうとしているのですが、1行目で**list
の名前でリスト変数を定義してしまったことで、list
の参照先が上書きされてしまったのです。**
そのためこのコードでは今後list
が組み込み関数のlist()
ではなく変数の["Apple", "Orange", "Grape"]
を参照するようになります。
残念ながらこのコード内では再代入しない限りlist()
関数は二度と使えません。
対策
同じように使用を強く非推奨される命名は他にもあり、str
、list
、int
、dict
、id
、bool
等も、一時変数に使いたくなる魅力を放ちながらも、実際に定義してしまうと同名の関数を潰してしまうことになる危険なものとなっています。
たとえ書き捨てコードであっても、これらの命名は決して使ってはいけません。
そこで、個人的なおすすめの命名は、これらを接尾辞として変数名の一部に入れることです。
上記の例であれば、
list = ["Apple", "Orange", "Grape"]
tuple = ("Peach", "Strawberry")
を、
fruits_list = ["Apple", "Orange", "Grape"]
fruits_tuple = ("Peach", "Strawberry")
のように**、[リストの抱える要素の総称]_[データ型]
**の命名が、入っているデータの内容と型を容易に判別できるのでおすすめです。
命名はできるだけ一意なものが望ましい
組み込み関数だけでなく、同名のオブジェクトが存在する命名は避けたほうが幸せ
今回上げた例はlist()
という関数の話ですが、Pythonでは予約語以外のあらゆる変数を自由に定義・代入できてしまうという特性があり、注意しないと変数の上書きや関数へのアクセスを失ってしまうことになるので、変数は**「他と被らない命名」**をできるだけ心がけるといいと思います。
標準組み込み関数だけでなく、コード内やimportしたパッケージに存在するメソッドとの競合も気をつけてるべきでしょう。
コードサジェスト機能が存在するエディタなら、新規変数を定義しようとしたとき、サジェストに同一名の候補が列挙されたら使用しないという手も有効かもしれません(下画像はVisualStudioCodeのサジェスト)。
まとめ
- 同一名の関数/変数が存在する変数を新たに定義してしまうと、関数が使えなくなってしまったり、その前に定義されていた変数の値を失うことになる。
- 変数の命名は
[リストの抱える要素の総称]_[データ型]
が、安全かつ可読性に優れた例としておすすめ - キーワードサジェストを参考に変数命名アンチパターンを回避できる。
変数名に注意を払うようになると、可読性がぐっと上がり、コード全体の処理過程も追いやすくなります。
これによりバグの早期発見の確率も上がり生産性の大きな向上も見込めるでしょう。
コードを書く際には変数の命名を見直してみてください。
最後まで読んでいただきありがとうございましたm(_ _)m
修正点、加筆すべきことありましたら教えていただけると幸いです。