前回はモジュールの読み込みと関数の再利用方法を見てきました。
今回は、辞書データ型を詳しく見ながら、
モジュールの知識も使ってコードを組んでみます。
次回は Google MediaPipe(Face Mesh)の準備として、
csvモジュールとwith構文の使い方を解説します。
※ MediaPipe とは Google が開発する機械学習(AI)システムです。
以前解説したノートブックの使い方を前提に説明していきます!
辞書型で値に名前をつける
以前説明したリストと似た性質を持つ
辞書(ディクショナリ)データ型について説明します。
辞書データ型とはその名の通り、
辞書のような役割を持ったデータ型になります。
具体的には名前:key(キー)と
値:value(バリュー)を持ったデータ型で、
関連づけ(マッピング)を行いたいときに使います。
たとえば、ネットショッピングなどのほしい物一覧(お買い物カート)には
あなたの欲しい商品とその値段が関連づけられているかと思います。
仮に値段だけが並んだ商品一覧を想像してみて欲しいのですが、
数字だけをみて商品名を推測するのは難しいと思います。
こういった直感的に分かりづらい情報には名前をつけて、
管理しやすくしようとするのが辞書型です。
実際に辞書データ型を定義してみましょう。
リストの定義とよく似ています。
# 辞書データ型は波カッコで定義する
wish_bag = {}
print(type(wish_bag))
出力:
<class 'dict'>
以前説明したtype( )関数を使って、変数のデータ型を調べると、
‘dict’ と出力され、ディクショナリ型であることが分かります。
次に商品名と値段を関連づけていきます。
ここでは三冊の(架空の)本が欲しいとします。
商品名と値段(税抜)は次のとおりです。
商品名 | 値段 |
JUVETと猫 | 1800円 |
JUVETのお家 | 1600円 |
JUVETの仲間たち | 2400円 |
これらの商品と値段をマッピングするには次のように書きます。
# 辞書['キー'] = バリューで商品名とその値段を追加していく
wish_bag['JUVETと猫'] = 1800
wish_bag['JUVETのお家'] = 1600
wish_bag['JUVETの仲間たち'] = 2400
print(wish_bag)
出力:
{'JUVETと猫': 1800, 'JUVETのお家': 1600, 'JUVETの仲間たち': 2400}
このように書くことで、マッピングができるようになります。
また、リストと同じように
辞書を作成する時点で値を入れることもできます。
# 次のように定義することもあります{'キー': バリュー, ...}
wish_bag = {
'JUVETと猫': 1800,
'JUVETのお家': 1600,
'JUVETの仲間たち': 2400
}
print(wish_bag)
ここでは、キーとバリューのセットを1行に1つだけ書いて改行しています。
これはプログラムが横に長くならないようにするための工夫で、
よく利用される書き方になります。
次はこの辞書をfor文で回してみましょう。
辞書データ型はイテラブルなので、繰り返し処理ができるのです。
# for文で値を取りしてみると
for key in wish_bag:
print(key)
出力:
JUVETと猫
JUVETのお家
JUVETの仲間たち
お気づきだと思いますが、この書き方で取り出されるのはキーのみになります。
バリューも同時に取り出すには、次のように書きます。
# バリューも取り出すには辞書型の .items()を使う
for k, v in wish_bag.items():
print(k, v)
出力:
JUVETと猫 1800
JUVETのお家 1600
JUVETの仲間たち 2400
辞書データ型に用意された .items( )を使うと、
キーとバリューを同時に取り出すことができます。
詳しくは次回解説しますが、
これはメソッドと呼ばれるもので、関数と同じように扱うことができます。
注意すべきはドット( . )です。忘れずに先頭につけましょう。
また、2つの値を取り出すので変数も2つ(k と v)必要になります。
今回は key と value の頭文字からそれぞれ k と v にしています。
しかし、出力を見てみると、
キーとバリューが続けて書かれており、
何だか見づらい印象を与えてしまいます。
以前説明した「見やすさ」をもう少し拡張すると、
次に説明する文字の埋め込みにたどり着きます。
変動する値だけを変えて表示したいときはf-stringを使う
文字列の中に変数を埋め込みたいときには、
f-string(フォーマット済み文字列)を使います。
公式ドキュメントには次のような説明があります。
置換フィールドを含めることができます。
— 2.4.3. フォーマット済み文字列リテラル —
まずフォーマット(書式のこと)とは、どのように表示するかということを表しており、
この場合は、文字列として表示するという意味で使われます。
また引用にある「置換フィールド」は波かっこの中を指しており、
もしこのフィールドに変数を書くと、
その変数に代入されている値で置換されるということです。
値に応じて、文章の一部のみを変更したいときに使います。
構文は以下の通りです。
f'ここに文字列を書きます。{変数}ここにも文字列があっても良い。'
実際に書いてみましょう。
# 変数を用意(埋め込みたい値を代入する)
temperature = 26
# f'文字列{変数}'と書くことで、変数を文字列に埋め込むことができます
print(f'今日の温度は{temperature}度です。')
出力:
今日の温度は26度です。
print( )関数内の先頭にある f がフォーマット済みを表し、
文字列内の波かっこの中に、埋め込まれる変数を書きます。
この例では、temperature 変数の26という値が
print( )内にある文字列に埋め込まれました。
このように f-string を使うことで、
コードを変更することなく、変数の値に応じた文章を書くことができるようになります。
今度はこのf-string と、
先ほどの for文を使って辞書型のキーとバリューを出力します。
# k(商品名)と v(値段)が文字列に埋め込まれる
for k, v in wish_bag.items():
print(f'商品名: 「 {k} 」, 定価: {v}円')
商品名: 「 JUVETと猫 」, 定価: 1800円
商品名: 「 JUVETのお家 」, 定価: 1600円
商品名: 「 JUVETの仲間たち 」, 定価: 2400円
これで少しは辞書のキーとバリューが見やすくなったかと思います。
次は定価だけを表示するのではなく、
以前作成した tax( )関数を使って税込み価格も表示してみましょう。
小数点以下もf-stringで指定できる
コードは先ほどとほとんど同じですが、
tax( )関数を使用できるように、
まずは前回学んだように、taxモジュールの読み込みを行います。
from tax import tax
for k, v in wish_bag.items():
# tax()関数を適用
pay = tax(v)
print(f'商品名: 「 {k} 」, 定価: {pay}円')
出力:
商品名: 「 JUVETと猫 」, 税込価格: 1980.0000000000002円
商品名: 「 JUVETのお家 」, 税込価格: 1760.0000000000002円
商品名: 「 JUVETの仲間たち 」, 税込価格: 2640.0円
tax( )関数の使い方は前回説明した通りで、
今回の場合、値段 v を入力すると、税込価格 pay が得られます。
税込価格まで表示できるのはいいですが、
小数点以下が多すぎます。
これは定価である整数の値段に対して、
浮動小数点数で計算しているために
小数点以下まで細かく表示されてしまっています。
今回はせっかくなので、
先ほどの f-string で対応しましょう。
たとえば次のように書くことで、
小数点以下の2桁まで考慮した表示が指定できます。
f'{variable:.2f}' # variableは数字が代入された変数とします
ただし今回は、整数で表示したいので小数点以下が必要ありません。
そのため、小数点以下は0桁まで表示するように指定します。
from tax import tax
for k, v in wish_bag.items():
pay = tax(v)
# 小数点以下0桁までを表示する
print(f'商品名: 「 {k} 」, 税込価格: {pay:.0f}円')
出力:
商品名: 「 JUVETと猫 」, 税込価格: 1980円
商品名: 「 JUVETのお家 」, 税込価格: 1760円
商品名: 「 JUVETの仲間たち 」, 税込価格: 2640円
これで想定する出力が得られました。
次は辞書データ型の内包表記を見てみましょう。
以前、リストの内包表記を解説しましたが、
辞書型も内包表記でまとめることができます。
最終回(次回の次)で Google MediaPipe(Face Mesh)を取り扱いますが、
辞書データ型の内包表記は、そこでも登場する書き方なので、
ここで押さえるようにしましょう。
辞書型も内包表記でコンパクトにできる
辞書データ型内包表記の書き方は以下の通りです。
{k: v for k, v in イテラブルなデータ型}
構文はリストの内包表記とほとんど同じです。
異なるのは for文の左側で、
先ほど説明した辞書型の定義方法と同じように、
コロンの左にキー、右にバリューを書くところです。
ここで辞書そのものを定義していることになります。
このことを踏まえて
先ほどの結果を辞書の内包表記で書いてみましょう。
from tax import tax
wish_bag2 = {title: tax(v) for title, v in wish_bag.items()}
print(wish_bag2)
出力:
{'JUVETと猫': 1980.0000000000002, 'JUVETのお家': 1760.0000000000002, 'JUVETの仲間たち': 2640.0}
内包表記で作成した辞書を wish_bag2 としています。
また、商品名に相当するキーは変数 title で、
税込価格には tax(v)を直接渡しています。
このように関数を直接書くと、
その関数の出力(税込価格)がバリューとして定義されることになります。
このコードから分かるように、
内包表記でも関数を適用することができます。
それから、先ほどは f-string で小数点以下に対応しましたので、
出力結果は文字列に変換されていましたが、
今回は float型で小数点以下まで表示されています。
これを改善するために、四捨五入ができる decimalモジュールを使います。
このモジュールで整数値のバリューを辞書に入れていきます。
decimalモジュールで四捨五入しよう
ここから外部モジュールを使っていきます。
以前お話ししたように、
基本的な機能は、すでに開発されていると考えましょう。
ここで行いたいことは、
税込価格を整数で表示することになります。
そのために、
まずは四捨五入できるモジュールを読み込みます。
Python で四捨五入を行いたい場合には、
decimalモジュールを使いましょう。
公式ドキュメントには以下の記述があります。
十進数を正確に表現できます。
—decimal
— 十進固定及び浮動小数点数の算術演算—
実はこれまでに登場した floatデータ型はたしかに小数点を表現しますが、
コンピュータ上で表示するときは、近似された値が採用されます。
これはコンピュータが十進数(decimal)ではなく、
二進数(0と1のみで表現された数)で計算を行うために生じる誤差です。
といっても通常の計算をする上では、ほとんど気にならない程度のものです。
詳しくは公式ページで説明されているので、興味がある方は参照しましょう。
四捨五入を行う前に、
まずは前回説明した !touch コマンドを使い、
新たに tax2.py を作成します。
!touch tax2.py
pythonファイルの具体的な作成手順は、前回説明しました!
作成された tax2.py に以下のコードを貼り付けて保存します。
from decimal import Decimal, ROUND_HALF_UP
def tax(amount):
result_f = amount * 1.1
result_int = Decimal(str(result_f)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)
return result_int
ここでは decimalモジュールから
Decimal と ROUND_HALF_UP を読み込んでいます。
以前説明したように、
何らかの処理を実現したいときには既存の関数等を使ってコードを組んでいきます。
ここでは詳細には踏み込まないですが、
このモジュールを使うことで数字の四捨五入を行うことができる
と理解しましょう。
実現したい機能を持つモジュールを適切に使いましょう!
次にセル上で tax2.py を読み込み、以下を実行します。
from tax2 import tax
wish_bag3 = {title: tax(v) for title, v in wish_bag.items()}
print(wish_bag3)
出力:
{'JUVETと猫': 1980, 'JUVETのお家': 1760, 'JUVETの仲間たち': 2640}
この辞書を見ると、商品名と値段が関連づけられており、
想定する「欲しいもの一覧」が作成できました。
この記事の最初の方で、
「辞書のような役割を持つ」と言いましたが、
その理由が分かっていただけたかと思います。
たとえば、
「book」を英和辞書で調べたとしましょう。
この場合 book には、おそらく「本」という単語が関連づけられており、
「”book” イコール 本」という関係が見えてきます。
同様に先ほど作成した辞書でも、
商品名とその値段が関連づけられており、
「”JUVETと猫” イコール 1980」であるということです。
最後に辞書データ型へのアクセス方法を解説します。
角かっこで辞書データ型にアクセスできる
以下のように辞書にキーを指定することで、
そのバリューにアクセスできるようになります。
キーを角かっこ([ ])で挟みます。
dict['key'] # dictは辞書データ型
ルール9: 辞書データ型のキーでバリューにアクセスします!
たとえば「商品名 “JUVETと猫” はいくらだったかな?」と思ったとします。
その場合は商品名であるキーを使って、以下のように書くことで、
そのバリューが取り出せるというわけです。
# 商品「JUVETと猫」の値段を取り出す場合
print(wish_bag3['JUVETと猫'])
出力:
1980
また、次のように存在しないキーを指定すると例外が発生しますので、
辞書に定義されているキーを把握した上でアクセスするようにしましょう。
print(wish_bag3['猫'])
出力:
KeyError: '猫'
このように辞書データ型を使うことで、
名前と値(データ)を関連づけることができるのです。
少々長くなりましたが、
辞書データ型はプログラムによく登場しますので、
覚えておくようにしましょう。
次回はこの辞書の結果を csvファイルに書き込むところから始め、
with構文でファイルとして保存するところまで行います。
まとめ
今回は辞書データ型の定義方法とその内包表記について学びました。
内包表記は Pythonプログラミングでよく利用される書き方なので、
これを機に慣れておくと良いでしょう。
また、f-string を使うことで
文字列に変数の埋め込みができることもお伝えしました。
こちらもよく目にする書き方ですので、押さえるようにしましょう。
今回出てきたルールは以下の通りです。
ルール9: 辞書データ型のキーでバリューにアクセスする
内容についてご質問があればコメント欄からどうぞ。
次回は csvモジュールを使い、ファイル内に書いた内容を
csvファイル に保存する方法(with構文)を見ていきます。
これができると、
プログラムで処理した内容を外部ソフトでも利用できるようになります。
【P.S.】
ちなみに Pythonプログラミングの基本的な内容は次回で終わりです。
最終回は Google MediaPipe(Face Mesh)で
次の画像のように
顔のメッシュを取り出して csvファイルに保存する会にしようと考えています。
@AI_JUVETをフォローしていただけると大変励みになります🙂
参考
— decimal
— 十進固定及び浮動小数点数の算術演算 —
コメント