Python におけるキーワードと組み込み識別子

PythonBeginner
オンラインで実践に進む

はじめに

この実験(Lab)では、Python の予約語と組み込み名の基本的な概念を探求します。まず、変数名や関数名として使用できない、特定の意味を持つ特別な単語である Python のキーワードを特定する方法を学習します。これには、組み込みの keyword モジュールを使用します。

次に、コード内で常時利用可能な関数や定数など、Python の組み込み識別子を発見します。最後に、エラーを防ぎ、コードをクリーンで機能的に保つために、独自の命名にキーワードや組み込み識別子を使用することを避けることがなぜ重要なのかを理解します。

Python キーワードの特定

このステップでは、Python のキーワードについて学習します。予約語とも呼ばれるキーワードは、言語の構文の基本的な構成要素です。これらは特別な意味を持ち、変数、関数、その他の識別子の名前として使用することはできません。

Python には keyword という組み込みモジュールがあり、これにより現在のすべてのキーワードを簡単に確認できます。それらを表示するためのスクリプトを記述しましょう。

必要なファイル list_keywords.py はすでに作成されています。WebIDE の左側にあるファイルエクスプローラーでそれを見つけ、クリックして開いてください。

次に、list_keywords.py ファイルに次のコードを追加します。

import keyword

## kwlist 属性には、すべてのキーワードのリストが含まれています。
print(keyword.kwlist)

ファイルを保存した後、WebIDE の統合ターミナルを開きます。これは、上部メニューの Terminal -> New Terminal をクリックすることで実行できます。

ターミナルで次のコマンドを実行して、スクリプトを実行します。

python ~/project/list_keywords.py

出力は、すべての Python キーワードのリストになります。

['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

これらの単語が予約されていることを覚えておくことが重要です。Python は大文字と小文字を区別するため、if はキーワードですが、IF はキーワードではありません。ただし、コードの明確性を維持するために、キーワードのいかなるバリエーションも名前として使用しないことが最善の慣行です。

Python の組み込み識別子の探索

次に、Python の組み込み識別子を探求します。これらは、print() のような一般的な関数、intstr のようなデータ型、例外など、Python が事前に定義しておく名前です。これらは、import 文を必要とせずに、どの Python スクリプトでも常時利用可能です。

__builtins__ と呼ばれる特別なオブジェクトに対して dir() 関数を使用することで、すべての組み込み識別子のリストを表示できます。

ファイルエクスプローラーから list_builtins.py ファイルを開きます。以下のコードをファイルに追加します。

## dir() は __builtins__ スコープ内の名前のリストを返します。
print(dir(__builtins__))

ファイルを保存し、ターミナルからスクリプトを実行します。

python ~/project/list_builtins.py

コンソールに長い名前のリストが出力されるのが確認できます。以下は出力の抜粋版です。

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

このリストの中には、leninputlistdict のような多くの便利な名前が見つかるでしょう。次のステップでは、なぜこれらの名前を独自の変数に使用することを避けるべきなのかを見ていきます。

識別子としてキーワードの使用を避ける

このステップでは、Python のキーワードを変数名として使用しようとした場合に何が起こるかを確認します。キーワードは言語の構造のために予約されているため、それに値を代入しようとすると、プログラムは実行される前に失敗します。

キーワード with を変数名として使用しようとすることで、これを実証してみましょう。

WebIDE エディタでファイル keyword_error.py を開きます。意図的に誤った次のコードを追加します。

## これは 'with' がキーワードであるためエラーになります。
with = 5
print(with)

ファイルを保存し、ターミナルから実行してみます。

python ~/project/keyword_error.py

Python は直ちに停止し、SyntaxError を報告します。

  File "/home/labex/project/keyword_error.py", line 2
    with = 5
    ^^^^
SyntaxError: invalid syntax

エラーメッセージ SyntaxError: invalid syntax は、コードの構造が間違っていることを明確に示しています。これは、Python インタープリタが withwith ステートメントを開始するために使用されるキーワードとして認識し、値を保持できる名前としては認識しないために発生します。このルールは、最初のステップでリストアップしたすべてのキーワードに適用されます。

組み込み識別子の意図しない上書きを避ける

キーワードとは異なり、Python は組み込み識別子の再代入を妨げません。しかし、これを行うことはバグの一般的な原因となるため、避けるべきです。組み込みの名前に新しい値を代入すると、その本来の機能を「隠蔽」してしまい、予期せぬエラーにつながる可能性があります。

組み込みの print 関数を上書きした場合に何が起こるかを見てみましょう。

WebIDE エディタでファイル builtin_override.py を開きます。以下のコードを追加します。

## 組み込みの print 関数を整数で上書きします。
print = 5

## ここで、print() を関数として使用しようとします。
print("hello")

ファイルを保存し、ターミナルから実行します。

python ~/project/builtin_override.py

今回は、スクリプトは実行を開始しますが、TypeError で失敗します。

Traceback (most recent call last):
  File "/home/labex/project/builtin_override.py", line 5, in <module>
    print("hello")
TypeError: 'int' object is not callable

エラー TypeError: 'int' object is not callable は、名前 print がもはや組み込みの印刷関数を参照していないために発生します。代わりに、整数 5 を参照しています。整数を関数のように「呼び出す」(括弧を使用する)ことはできないため、プログラムはクラッシュします。

これは、組み込みを上書きすることの危険性を示しています。これは、分かりにくい方法でコードを壊し、デバッグを困難にする可能性があります。これらの競合を避けるために、変数や関数には常に一意で説明的な名前を選択してください。

まとめ

この実験(Lab)では、Python における名前の重要な 2 つのカテゴリ、すなわちキーワードと組み込み識別子について学習しました。keyword モジュールを使用して Python の予約済みキーワードをすべてリストアップし、それらを変数名として使用しようとすると SyntaxError になることを確認しました。

また、組み込み識別子のリストを調査し、それらを上書きすることによって生じる問題(TypeError やその他の実行時エラーにつながる可能性がある)を実証しました。重要な教訓は、コードが堅牢で、読みやすく、競合がないことを保証するために、変数や関数には常に一意の名前を選択し、キーワードと組み込み名の両方を避けることです。