ダウンロード サンプルファイル (3.0 KB)
省略や無効を明確に示す! 番兵値を明確に表すsentinel型で曖昧さを排除
関数の引数が省略されたことや、戻り値が特別な状態を示すことを表すために、番兵値(センチネル)を使うことがあります。
たとえばNoneを使って引数の省略を表す方法がありますが、呼び出し側がNone自体を値として渡したい場合には、省略された場合と区別できません。
Python 3.15では、組み込みのsentinelを使って、一意の番兵値を簡潔に作成できるようになりました。これにより、Noneなどの通常の値とは区別できる目印を用意できます。
以下のリストは、sentinelの基本的な使い方を示したものです。
OMITTED = sentinel("OMITTED") (1)
def describe_name(name=OMITTED): (2)
if name is OMITTED: (3)
return "名前は指定されていません"
if name is None: (4)
return "名前にNoneが指定されました"
return f"名前: {name}"
print(describe_name()) # 名前は指定されていません
print(describe_name(None)) # 名前にNoneが指定されました
print(describe_name("やまだ")) # 名前: やまだ
このコードでは、引数が省略された場合と、Noneが明示的に渡された場合を区別しています。
(1)では一意の番兵値を作成し、変数OMITTEDに代入しています。この値を表示すると、既定ではOMITTEDと表示されます。
(2)では、引数nameのデフォルト値にOMITTEDを指定しています。引数を省略すると、この番兵値が使われます。(3)では、is 演算子で引数が番兵値と同一かどうかを判定しています。sentinelで作成した値は、それ自体との同一性をisで判定するのが基本です。
一方、(4)の「name is None」は、引数にNoneが渡されたかどうかを判定します。このように番兵値を利用すれば、引数の省略と、Noneを値として指定することを明確に区別できます。
内包表記におけるアンパッキング
Python 3.15では、リスト、セット、辞書の内包表記とジェネレータ式で、*や**を使ったアンパック構文を利用できるようになりました。これにより、複数の反復可能オブジェクトや辞書の内容を、簡潔な構文で1つにまとめられます。
まず、内包表記の基本を確認しましょう。内包表記は、反復処理などを使ってリストやセット、辞書を簡潔に作成するための構文です。次の例では、range(10)から偶数を取り出し、それぞれの自乗を計算したリストを作成しています。
squares = [number * number for number in range(10) if number % 2 == 0] print(squares) # [0, 4, 16, 36, 64]
一方、ジェネレータ式は、値を一度にすべて生成するのではなく、必要に応じて順番に取り出せるオブジェクトを作成する構文です。リスト内包表記と似ていますが、角かっこ[]の代わりに丸かっこ()を使います。得られるのはイテラブルオブジェクトなので、以下のリストのようにnextやlistを使って値を取り出します。
squares = (number * number for number in range(10) if number % 2 == 0) print(next(squares)) # 0 print(next(squares)) # 4 print(list(squares)) # [16, 36, 64]
なお、yieldを使って定義するジェネレータ関数も、値を順番に生成する仕組みですが、ジェネレータ式とは別の構文です。ジェネレータ式では複雑になるような処理を表現するのに向いています。
def calc_square(limit):
for number in range(limit):
if number % 2 == 0:
yield number * number
for value in calc_square(10):
print(value, end=" ")
print() # 0 4 16 36 64
Python 3.15の新しいアンパック構文を使うと、内包表記の各反復で得られた反復可能オブジェクトの要素を、*で展開してまとめられます。また、辞書の内包表記では、**を使って辞書のキーと値の組を展開できます。ジェネレータ式でも、*による展開を利用できます。
以下のリストで、それぞれの使い方を確認しましょう。
lists = [[1, 2], [3, 4], [5]]
# リストのリストを平坦化する
flat = [*items for items in lists]
print(flat) # [1, 2, 3, 4, 5]
# 辞書からは**を使って取り出す
dicts = [{"a": 1}, {"b": 2}, {"a": 3}]
combined = {**item for item in dicts}
print(combined) # {'a': 3, 'b': 2}
# ジェネレータ式
generator = (*items for items in lists)
print(next(generator)) # 1
print(next(generator)) # 2
print(list(generator)) # [3, 4, 5]
最初の例では、各リストの要素を*で展開し、1つのリストにまとめています。従来の内包表記であれば、[item for items in lists for item in items]と書く処理に相当します。
2番目の例では、各辞書のキーと値の組を**で展開し、1つの辞書にまとめています。同じキーが複数回現れた場合は、後から展開された値が採用されます。この例では、キーaの値が3になります。
最後の例では、ジェネレータ式によって、各リストの要素を順番に生成するジェネレータを作成しています。nextを呼び出すたびに次の要素が得られ、残りの要素はlistでまとめて取り出せます。
このように、Python 3.15のアンパック構文を使うと、複数のリストや辞書をまとめる処理を、従来より簡潔に記述できます。
この記事は参考になりましたか?
- Pythonの新機能を知ろう!連載記事一覧
-
- Python 3.15の新機能――明示的な遅延インポートとイミュータブルな辞書型などを解説
- Python 3.14の新機能――フリースレッドPythonの正式サポートと高速化などを解...
- Python 3.14の新機能――再利用可能なテンプレート文字列や高効率な圧縮ライブラリを...
- この記事の著者
-
WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
