PHPにはissetという便利な言語構造があります。issetは渡された値が定義済みかつnullでないならばtrueを返す関数のように動作する機能です。これを実際に使うと次のようになります。
<?php function main() { $hoge = 1; $piyo = null; var_dump(isset($hoge)); // bool(true) $hogeは1のため var_dump(isset($fuga)); // bool(false) $fugaは未定義のため var_dump(isset($piyo)); // bool(false) $piyoはnullのため } main();
未定義変数とnullを同時にチェックできるのは便利ですが、他言語でこの機能を備えているものはそれほど多くありません。これは処理速度、思想など色々な理由です。実際、他言語でも工夫で似たようなことができることはよくあります。この記事ではPythonでPHPのissetのようなことをする関数の作り方の例を紹介します。
実際のコードと実行例が次です。
ソースコード
import inspect def isset(var_name: str) -> bool: """ PHPのissetに近い動きをする関数。引数は調査対象の変数名 """ # この関数が呼び出されたスコープをトレースバックで参照して、 # そのスコープにおけるローカル変数とグローバル変数の一覧を取得する caller_locals = inspect.currentframe().f_back.f_locals caller_globals = inspect.currentframe().f_back.f_globals # 渡された変数名がローカル変数またはグローバル変数に存在し、かつNoneでないかを確認 return (var_name in caller_locals and caller_locals[var_name] is not None) or \ (var_name in caller_globals and caller_globals[var_name] is not None) def main(): hoge = 1 piyo = None print(isset('hoge')) # True hogeは1のため print(isset('fuga')) # False fugaは未定義のため print(isset('piyo')) # False piyoはNoneのため main()
issetを使いたいスコープの中で調査対象の変数が定義されているか、定義済みであるならばその値は None であるか、というのをチェックしています。通常、変数が定義されているか否かは locals 関数を使って自分のスコープ範囲のローカル変数を調べるか globals 関数でグローバル変数を調べるかするしかありませんが、inspect を使うと親スコープの変数も参照できます。inspectはPython組み込みモジュールの一つでメタ的な情報を得られます。これを利用することで通常はできない親スコープの変数の参照をしてisset関数を作っています。
inspect — 活動中のオブジェクトの情報を取得する — Python 3.12.1 ドキュメント
通常は宣言済みの変数しか参照しないようにコードの流れを作るのですが、try expectを抜けた後の処理などやんごとなき理由によってそうならない場合もあります。そういった際にこのような便利関数があるとより楽にプログラミングができます。