Lesson 5

入出力

Lesson 5 Chapter 1
print()

Lesson5からは、関数を使用したデータの入出力処理方法や、Web APIなどでデータのやり取りをする際に使用されているデータフォーマットの保存方法など、入出力処理に関する具体的な操作方法について解説していきます。

まずは、今までのレッスンでも画面出力をする際に頻繁に使用した、print関数について解説します。print関数は、Pythonが最初から提供している「組み込み関数」に分類されますが、これまで使用してきた以外の出力方法が多数あるので、覚えていきましょう。

バージョンによる違いについて

Pythonには、メジャーバージョンが2系と3系の2種類存在します。現在は、3系を使用することが増えてきていますが、それ以前の2系とはバージョンアップの際に、仕様が大きく変更されました。
print関数についても、バージョン間で違いが出ているので、まずはその点をおさえておきましょう。尚、このChapterでは、Python3系のprint関数についての解説がメインとなります。

Python2系では、print関数は「print文」として扱われています。関数ではないので、"()"を記述する引数の指定は不要でした。

print 'Hello World' #Python2系
print('Hello World') #Python3系

Python3系で2系と同じ"()"無しの記述をすると、「SyntaxError」が出力されエラーとなります。

print関数の使い方

print関数は、引数に値を設定することで、その値が画面出力可能になります。

文字と数値の出力

文字と数値の出力は、今までのレッスンで何度も実行してきましたが、改めて実行していきましょう。
文字列はダブルクォーテーション(")か、シングルクォーテーション(')で囲み、数値はそのままの値を"()"内に引数として指定します。

print_test.py
print('Hello World')
print(10)

出力結果

Hello World
10

文字と数値を混在させ、複数の値を引数に指定してみましょう。複数の値を指定するには、カンマ(,)区切りで指定します。

print2_test.py
print('Hello World', 10, 20, 'Python')

出力結果

Hello World 10 20 Python

変数の出力

変数の値を出力させるためには、変数名を指定します。

print3_test.py
word = 'Hello World'

print(word)

出力結果

Hello World

複数の変数を引数に指定してみましょう。変数をカンマ(,)区切りで指定します。

print3_test.py
word1 = 'Hello'
word2 = 'World'
word3 = 'Python'

print(word1, word2)
print(word1, word2, word3)

出力結果

Hello World
Hello World Python

リスト・タプル・辞書の出力

リストやタプル、辞書の要素を出力することも可能です。
まずは、リストの出力を行います。

print_lst_test.py
lst1 = [1,2,3,4,5,6,7,8,9]
lst2 = ['morning','afternoon','evening','night']

print(lst1)
print(lst2)
print(lst1, lst2)

出力結果

[1, 2, 3, 4, 5, 6, 7, 8, 9]
['morning', 'afternoon', 'evening', 'night']
[1, 2, 3, 4, 5, 6, 7, 8, 9] ['morning', 'afternoon', 'evening', 'night']

次に、タプルの出力を行いましょう。
タプルもリストと同じ方法で出力可能です。

print_tup_test.py
tup1 = (1,2,3,4,5,6,7,8,9)
tup2 = ('morning','afternoon','evening','night')

print(tup1)
print(tup2)
print(tup1, tup2)

出力結果

(1, 2, 3, 4, 5, 6, 7, 8, 9)
('morning', 'afternoon', 'evening', 'night')
(1, 2, 3, 4, 5, 6, 7, 8, 9) ('morning', 'afternoon', 'evening', 'night')

最後に、辞書の出力を行いましょう。

print_dct_test.py
d1 = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
d2 = {'morning': 'coffee', 'afternoon': 'Tea','evening': ' Beer'}

print(d1)
print(d2)
print(d1, d2)

出力結果

{'name': '山田', 'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com'}
{'morning': 'coffee', 'afternoon': 'Tea', 'evening': ' Beer'}
{'name': '山田', 'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com'} {'morning': 'coffee', 'afternoon': 'Tea', 'evening': ' Beer'}

辞書の出力では、キーとバリューのどちらも出力されます。

出力方法の応用

print関数の"()"内の引数へは出力したい値を設定してきましたが、それ以外にも出力方法を変える引数の設定が可能です。引数に応じて出力結果が変わります。

引数end

引数に「end」を指定することで、末尾に出力する値を指定することができます。実際に引数にendを指定した際の動作を確認してみましょう。

print_end_test.py
print('Hello', end = '&')
print('World')

出力結果

Hello&World

引数endの指定がない場合は、改行コード"\n"が出力されます。今までのprint関数利用時は、出力したい値のみを設定し、引数endの指定はしていませんでした。つまり、自動で改行コード"\n"が出力されていたことになります。print関数を実行した回数分、その結果が改行されて複数回出力されたのは、引数endの指定がなかったことが理由です。
引数endに値を設定しない場合は、改行が行われずにprint関数の実行回数分の出力が1行に纏めて出力されます。以下のコードを実行してみましょう。

print_end2_test.py
print('Hello', end = '')
print('World', end = '')
print('Python')

出力結果

HelloWorldPython

引数sep

引数「sep」は、出力時の区切り文字を指定することが可能です。

print_sep_test.py
print('morning', 'afternoon', 'evening', 'night') #引数sepなし
print('morning', 'afternoon', 'evening', 'night', sep = '&') #引数sepあり'&'
print('morning', 'afternoon', 'evening', 'night', sep = ',') #引数sepあり','

出力結果

morning afternoon evening night
morning&afternoon&evening&night
morning,afternoon,evening,night

リストの要素を引数sepで指定した区切り文字を付与して、アンパックすることも可能です。以下のサンプルコードは、リストlstにアスタリスク(*)を指定して全ての要素をアンパックし、引数sepで指定した区切り文字を付与して出力しています。

print_sep2_test.py
lst = [1,2,3,4,5,6,7,8,9]
print(*lst, sep = '-->')

出力結果

1-->2-->3-->4-->5-->6-->7-->8-->9

Lesson 5 Chapter 2
str(), repr()

このChapterでは、「str」と「repr」の2種類の文字列変換関数について解説します。2つは違いが区別しづらい関数でもありますので、しっかりと理解して進めるようにしましょう。

str関数

「str」関数は、引数に指定した任意のオブジェクトを文字列に変換します。文字列変換の必要性を理解するために、まずは、文字列に数値を連結した結果を出力する、以下のコードを実行してみます。

str_test.py
Ch = 2
print('Lesson5のChapter' + Ch)

出力結果

TypeError: can only concatenate str (not "int") to str

「TypeError」が出力され、エラーとなりました。これは、文字列型である"Lesson5のChapter"に、数値型となる変数Chの数値:2を連結させることができないからです。連結させるためには、数値型を文字列型に変換する必要があります。そこで必要になるのが、str関数です。
str関数を用いて、数値型を文字列型に変換したうえで、連結処理を行なってみましょう。

str_test2.py
Ch = 2
print('Lesson5のChapter' + str(Ch))

出力結果

Lesson5のChapter2

str関数は、リストやタプルにも使用が可能です。リストを例にコードを記述してみます。最初は、str関数を用いない場合のコードです。

str_test3.py
Ch_lst = [1,2,3,4,5]
print('Lesson5のChapter' + Ch_lst[1])

出力結果

TypeError: can only concatenate str (not "int") to str

「TypeError」が出力され、エラーとなりました。リストの要素をstr関数で文字列に変換するコードに変更します。

str_test3.py
Ch_lst = [1,2,3,4,5]
print('Lesson5のChapter' + str(Ch_lst[1]))

出力結果

Lesson5のChapter2

このように、数値型のオブジェクトはstr関数で文字列型に変換することが可能です。

repr関数

関数「repr」は、str関数同様に文字列型に変換する関数ですが、違うのは「Pythonが認識できるオブジェクト」に変換します。少し分かりづらいので、順を追って解説していきます。
まずは、str関数との違いをその出力結果から確認していきましょう。

repr_test.py
x = 'Hello World'
print(str(x)) #str関数
print(repr(x)) #repr関数

出力結果

Hello World
'Hello World'

repr関数の出力結果は、シングルクォーテーション(')で囲まれた文字列が出力されています。repr関数は、Pythonが認識できるオブジェクトに変換されているため、シングルクォーテーション(')が付いています。
では、Pythonが認識できるオブジェクトとはどういった意味なのでしょうか。ここでは、eval関数を使用して説明していきます。eval関数は、引数に与えられた文字列をPythonの式として評価し、その結果を返す関数です。補足としてeval関数について解説します。

eval_sample.py
result = eval('10 + 100')

print(result)

出力結果

110

引数に与えられた文字列"10 + 100"を式として評価して、その結果を返しています。シングルクォーテーション(')を外し、文字列でなくした場合はエラーになります。

result = eval(10 + 100)

print(result)

出力結果

TypeError: eval() arg 1 must be a string, bytes or code object

「TypeError」が出力され、エラーとなりました。このように、文字列を式として評価します。このeval関数を使用して、repr関数がどのような処理を行なっているか確認しましょう。

repr2_test.py
x = 'Python'
x_repr = repr(x) #repr関数実行

print('repr関数:', (len(x_repr)))

出力結果

repr関数: 8

repr関数実行後にオブジェクトの長さを取得するlen関数を使って出力した結果、8が出力されました。len関数の結果から、repr関数後のオブジェクトの長さは、シングルクォーテーション(')を含んだ「'Python'」の長さであることが確認できます。

eval関数の処理を追加します。

repr3_test.py
x = 'Python'
x_repr = repr(x) #repr関数実行

print('repr関数:', (len(x_repr)))

repr_type = eval(x_repr) #eval関数実行

print(repr_type)

出力結果

repr関数: 8
Python

eval関数で式の評価結果を出力しています。eval関数が正常に処理されたことから、引数として与えられたrepr関数実行後のオブジェクトは、文字列型であると判断できます。
同様の処理をstr関数で行い、その違いを明らかにしましょう。

repr4_test.py
x = 'Python'
x_str = str(x) #str関数実行

print('str関数:', (len(x_str)))

出力結果

str関数: 6

repr関数と時とは違い、len関数で取得したオブジェクトの長さは6になりました。この結果から、str関数後の文字列はシングルクォーテーション(')を含まない「Python」の長さであることが確認できます。

repr関数のコード同様に、eval関数の処理を追加します。

repr5_test.py
x = 'Python'
x_str = str(x) #str関数実行

print('str関数:', (len(x_str)))

str_type = eval(x_str) #eval関数実行

print(str_type)

出力結果

NameError: name 'Python' is not defined

len関数の結果を出力する最初のprint関数の処理では、先程同様に「str関数: 6」が出力されたはずですが、eval関数の結果を出力する2回目の出力処理では、「NameError」が出力されエラーになりました。つまり、eval関数に与えられたstr関数後のオブジェクトは、文字列ではないということになります。
これは、文字列には種類があるということを意味しています。それは、「人間が読める表現」と「Pythonが理解する文字」ということです。str関数は人間が読める表現に変換し、repr関数はPythonが理解する文字に変換するということになります。
同じ文字列型変換の関数ですが、このような違いがあるので覚えておきましょう。通常は、str関数を使用した文字列型への変換を行うことが多いです。

Lesson 5 Chapter 3
フォーマット済み文字列リテラル

プログラミムを行なっていく中では、文字列をある一定のルールで出力させたいといった場面が出てくるはずです。例えば、数値に通貨単位の"円"を付与したり、決まった桁数で出力させるために足りない桁分は0で埋めるなど、文字列に対する書式を決めることができれば文字列の扱いが簡単になります。このChapterでは、そんな文字列に対する書式の指定方法を解説します。

フォーマット済み文字列リテラルとは

文字列リテラルとは、プログラムで記述される0文字以上の連続した定数を意味します。定数は、変数と同様に値を入れておく箱ですが、変数とは違い変更できません。
文字列リテラルを理解したうえで、今回解説する「フォーマット済み文字列リテラル」が何であるかを学んでいきましょう。
フォーマット済み文字列リテラルは、f文字列(f-strings)といい、Python3.6から利用できるようになった書式設定方法です。f文字列(f-strings)を使用した書式設定をいくつかの例をもとに確認していきます。

フォーマット済み文字列リテラルの記述方法

f文字列(f-strings)を使用して、書式を簡単に設定することができます。まずは簡単な記述方法として、「f'{変数名}'」とした際の動作を確認してみましょう。文字列の先頭は、"f" または "F"のどちらでも問題ありません。

f_test.py
name = '山田'
age = 25

print(f'私は{name}です。年齢は{age}歳です。')

出力結果

私は山田です。年齢は25歳です。

このように、波括弧{}で囲んだ部分に変数を入れることで、書式設定が可能になります。
今まで学んできた通常の出力方法では、以下のような記述になります。

f_test2.py
name = '山田'
age = 25

print('私は', name, 'です。年齢は', age, '歳です', sep="")

出力結果

私は山田です。年齢は25歳です

カンマの指定方法

金額表示の際には、カンマを設定する方法が便利です。
「f'{値:,}'」として設定します。この指定のみで、千の位にカンマが設定されます。

f_test3.py
x = 1000000

print(f'{x:,}')

出力結果

1,000,000

通貨単位を合わせて出力し、金額表示にしてみましょう。

f_test3.py
x = 1000000

print(f'{x:,}円です。')

出力結果

1,000,000円です。

今回指定したカンマを別の値に変更することも可能です。「f'{値:_}'」として、アンダーバーに変更して実行してみましょう。

f_test4.py
x = 1000000

print(f'{x:_}')

出力結果

1_000_000

小数点の指定方法

「f'{値:.nf}'」と指定することで、小数点を何桁まで表示するのかを指定できます。"n"には小数点以下の桁数を指定します。

f_test5.py
x = 123.456789

print(f'{x:.1f}') #小数第一位
print(f'{x:.2f}') #小数第二位
print(f'{x:.3f}') #小数第三位

出力結果

123.5
123.46
123.457

小数の末尾は四捨五入されていることに注意しましょう。

有効桁数の指定方法

「f'{値:.ng}'」と指定することで、表示する有効桁数を指定できます。"n"には表示したい有効桁数を指定します。

f_test6.py
x = 123.456789

print(f'{x:.2g}') #有効桁数2桁
print(f'{x:.5g}') #有効桁数5桁
print(f'{x:.8g}') #有効桁数8桁

出力結果

1.2e+02
123.46
123.45679

「f'{x:.2g}'」は有効桁数2桁を指定していますが、これは実際の有効桁数3よりも少ないです。このような場合は、指数表示(e+02は10の2乗で100)となるので覚えておきましょう。
また、小数点の時と同様に四捨五入しているように見えますが、有効桁数表示では端数が0.5の場合、「丸め」という処理が行われています。偶数になるように切り捨てや切り上げされているので、その違いを以下のコードで確認します。

f_test7.py
x1 = 123.4
x2 = 123.5
x3 = 123.8
y1 = 124.4
y2 = 124.5
y3 = 124.8

print(f'{x1=:.3g}, {x2=:.3g}, {x3=:.3g}, {y1=:.3g}, {y2=:.3g}, {y3=:.3g}')

出力結果

x1=123, x2=124, x3=124, y1=124, y2=124, y3=125

端数が0.5の場合、123.5(変数x2)は、124で出力されていますが、124.5(変数y2)は、125ではなく124で出力されています。小数点以下が0.5より大きい124.8(変数y3)の際に、切り上げされていることに注意してください。

変数名の同時出力について

変数名の同時出力に、「f'{x1=}」の構文を使用して変数名の同時出力を行いました。これは、Python3.8で追加された機能であるため、それ以前のバージョンでは使用不可です。

+や%の指定方法

+符号を付与する

「f'{値:+}'」と指定することで、数値がプラスの時は+符号を付与することが可能です。マイナスの時は付与されません。

f_test8.py
x = 100
y = 1.5
z = -300

print(f'xは{x:+}。yは{y:+}。zは{z:+}。')

出力結果

xは+100。yは+1.5。zは-300。

変数zの値はマイナスなので、自動判断によって+符号は付与されていません。

%を付与する

「f'{値:.n%}'」と指定することで%表示が可能です。"n"には小数点以下の桁数を指定します。

f_test9.py
x = 1
y = 10

print(f'xは{x:%}。yは{y:%}。')

出力結果

xは100.000000%。yは1000.000000%。

指定した値が100倍されて出力されるので、注意してください。
小数点以下の桁数を指定して、見やすくしましょう。

f_test9.py
x = 1
y = 10

print(f'xは{x:.0%}。yは{y:.0%}。')

出力結果

xは100%。yは1000%。

小数点以下の桁数をもう1パターン記述してみます。

f_test10.py
x = 123.456789
y = 987.654321

print(f'xは{x:.2%}。yは{y:.3%}。')

出力結果

xは12345.68%。yは98765.432%。

出力結果から「f'{値:.n%}'」のnの値が、小数点以下の桁数指定となっていることがわかると思います。

数値のゼロ埋め方法

桁数を揃えるために、不足している分の桁をゼロで埋めて桁数を統一にしたい場合は、「f'{値:0=n'}」と指定します。"n"には表示させたい桁数を指定します。

f_test11.py
x = 123
y = 45

print(f'xは{x:0=8}。yは{y:0=8}。')

出力結果

xは00000123。yは00000045。

桁数指定を8に設定したので、不足している分はゼロで埋めて8桁で出力されています。

小数点を含んだ値をゼロ埋めする際は、注意が必要です。小数点を含めて指定した桁数になるようにゼロ埋めされます。実際に確認しましょう。

f_test12.py
x = 0.123
y = 12.3

print(f'xは{x:0=8}。yは{y:0=8}。')

出力結果

xは0000.123。yは000012.3。

桁数指定を8に設定しましたが、出力結果は小数点を含めて8桁になっています。

文字埋め方法

ゼロ埋め同様に、桁数を揃えるために不足している分の桁を、文字で埋めて桁数を統一させることも可能です。「f'{値:a>n}’」と指定します。"a"には埋めたい文字を指定して、"n"には表示させたい桁数を指定します。

f_test13.py
x = 123
y = 45

print(f'xは{x:X>8}。yは{y:X>8}。')

出力結果

xはXXXXX123。yはXXXXXX45。

表示位置の指定

右寄せや、中央揃えといった表示位置の指定も可能です。

右寄せ

「f'{値:>n}’」と指定することで、右寄せで表示することができます。"n"には表示させたい桁数を指定します。

f_test14.py
name = '山田'
age = 25

print(f'私は{name:>5}です。年齢は{age:>5}歳です。')

出力結果

私は   山田です。年齢は   25歳です。

nに5を指定したので、5桁の右寄せで表示されました。

左寄せ

「f'{値:<n}’」と指定することで、左寄せで表示することができます。"n"には表示させたい桁数を指定します。

f_test15.py
name = '山田'
age = 25

print(f'私は{name:<5}です。年齢は{age:<5}歳です。')

出力結果

私は山田   です。年齢は25   歳です。

nに5を指定したので、5桁の左寄せで表示されました。

中央揃え

「f'{値:^n}’」と指定することで、中央揃えで表示することができます。"n"には表示させたい桁数を指定します。

f_test16.py
name = '山田'
age = 25

print(f'私は{name:^4}です。年齢は{age:^4}歳です。')

出力結果

私は 山田 です。年齢は 25 歳です。

nに4を指定したので、4桁の中央揃えで表示されました。

リスト・タプル・辞書の指定方法

リスト・タプル・辞書もf文字列(f-strings)でが扱うことが可能です。

リスト

以下にリストを扱う際のサンプルコードを記述します。波括弧{}内にリストの要素を指定することで、f文字列でも扱うことが可能になります。

f_test17.py
lst = [1,2,3,4,5]

print(f'リスト出力1:{lst[0]}')
print(f'リスト出力2:{lst[0:2]}')
print(f'リスト出力3:{lst}')

出力結果

リスト出力1:1
リスト出力2:[1, 2]
リスト出力3:[1, 2, 3, 4, 5]

複数のリストを扱ってみましょう。

f_test18.py
lst1 = [1,2,3,4,5]
lst2 = [6,7,8,9,10]

print(f'リスト出力:{lst1[0]},{lst1[1]},{lst1[2]},{lst2[0]},{lst2[1]},{lst2[2]}')

出力結果

リスト出力:1,2,3,6,7,8

タプル

次は、タプルの扱い方です。リスト同様になります。

f_test19.py
tup = (1,2,3,4,5)

print(f'タプル出力1:{tup[0]}')
print(f'タプル出力2:{tup[0:2]}')
print(f'タプル出力3:{tup}')

出力結果

タプル出力1:1
タプル出力2:(1, 2)
タプル出力3:(1, 2, 3, 4, 5)

複数のタプルを扱ってみましょう。

f_test20.py
tup1 = (1,2,3,4,5)
tup2 = (6,7,8,9,10)

print(f'タプル出力:{tup1[0]},{tup1[1]},{tup1[2]},{tup2[0]},{tup2[1]},{tup2[2]}')

出力結果

タプル出力:1,2,3,6,7,8

辞書

辞書を扱う際は、キーを指定することが可能です。f文字列の指定にシングルクォーテーション(')を使用しているので、キーの指定はダブルクォーテーション(")で囲んでください。

f_test21.py
name_dict = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

print(f'辞書出力1:{name_dict["name"]}')
print(f'辞書出力2:{name_dict["name"]}, {name_dict["mail"]}')
print(f'辞書出力3:{name_dict}')

出力結果

辞書出力1:山田
辞書出力2:山田, pythonlesson@gmail.com
辞書出力3:{'name': '山田', 'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com'}

複数の辞書を扱ってみましょう。

f_test22.py
name_dict_1 = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
name_dict_2 = {'name': '田中', 'TEL': '080-8765-4321','mail': 'sample@gmail.com'}

print(f'辞書出力:{name_dict_1["name"]}, {name_dict_1["mail"]}, {name_dict_2["name"]}, {name_dict_2["mail"]}')

出力結果

辞書出力:山田, pythonlesson@gmail.com, 田中, sample@gmail.com

波括弧の表示

波括弧{}を表示させたい場合は、表示させたい波括弧をさらに波括弧で囲んでエスケープすることで表示が可能になります。

f_test23.py
name = '山田'
age = 25

print(f'私は{name}です。年齢は{{age}}歳です。')

出力結果

私は山田です。年齢は{age}歳です。

想定した出力と違っていたのではないでしょうか。波括弧をエスケープすると、その中の変数や式もエスケープされます。このため変数ageの数値=25ではなく、変数名そのものが出力されました。
変数の値も表示させるためには、波括弧を2回記述する必要があります。

f_test23.py
name = '山田'
age = 25

print(f'私は{name}です。年齢は{{{age}}}歳です。')

出力結果

私は山田です。年齢は{25}歳です。

Lesson 5 Chapter 4
format()

前回のChapter3では、Python3.6から利用可能になったf文字列(f-strings)について学びましたが、Python3.6より前のバージョンで書式設定を行う場合は、メソッド「format」が利用可能です(Python3系であれば利用可能)。
f文字列と同じように書式設定方法を解説しますが、その設定方法の違いについてしっかりと理解していきましょう。

formatの記述方法

メソッド「format」の記述方法は、「'書式指定文字列{}'.format(置換フィールド)」です。記述方法のみではわかりにくいと思いますので、実際にf文字列と同様に簡単な記述を行い、その動作を確認しましょう。

format_test.py
name = '山田'
age = 25

print('私は{}です。年齢は{}歳です。'.format(name,age))

出力結果

私は山田です。年齢は25歳です。

波括弧{}の箇所が、format以降の置換フィールドで指定した文字列(今回は変数のnameとage)に置き換わり、書式設定ができました。f文字列よりも少し複雑な設定方法であることがわかると思います。

以下のコードのように、番号を用いて置換フィールドを紐付けることも可能です。

format2_test.py
name = '山田'
age = 25
birthplace = '東京'

print('私は{2}出身の{1}歳です。名前は{0}です。'.format(name,age,birthplace))

出力結果

私は東京出身の25歳です。名前は山田です。

カンマの指定方法

金額表示の際には、カンマを設定する方法が便利です。「'{:,}'.format(値)」として設定します。この指定のみで、千の位にカンマが設定されます。

format3_test.py
x = 1000000

print('{:,}'.format(x))

出力結果

1,000,000

通貨単位を合わせて出力し、金額表示にしてみましょう。

format3_test.py
x = 1000000

print('{:,}円'.format(x))

出力結果

1,000,000円

今回指定したカンマを別の値に変更することも可能です。「'{:_}'」として、アンダーバーに変更して実行してみましょう。

format4_test.py
x = 1000000

print('{:_}'.format(x))

出力結果

1_000_000

小数点の指定方法

「'{:.nf}'.format(値)」と指定することで、小数点を何桁まで表示するのかを指定できます。"n"には小数点以下の桁数を指定します。

format5_test.py
x = 123.456789

print('{:.1f}'.format(x)) #小数第一位
print('{:.2f}'.format(x)) #小数第二位
print('{:.3f}'.format(x)) #小数第三位

出力結果

123.5
123.46
123.457

小数の末尾は四捨五入されていることに注意しましょう。

有効桁数の指定方法

「'{:.ng}'.format(値)」と指定することで、表示する有効桁数を指定できます。"n"には表示したい有効桁数を指定します。

format6_test.py
x = 123.456789

print('{:.2g}'.format(x)) #有効桁数2桁
print('{:.3g}'.format(x)) #有効桁数3桁
print('{:.4g}'.format(x)) #有効桁数4桁

出力結果

1.2e+02
123
123.5

「'{:.2g}'」は有効桁数2桁を指定していますが、これは実際の有効桁数3よりも少ないです。このような場合は、指数表示(e+02は10の2乗で100)となるので覚えておきましょう。
また、小数点の時と同様に四捨五入しているように見えますが、有効桁数表示では端数が0.5の場合、「丸め」という処理が行われています。 指数表示や丸めについては、f文字列と同様の動作を行います。

+や%の指定方法

+符号を付与する

「'{:+}'.format(値)」と指定することで、数値がプラスの時は+符号を付与することが可能です。マイナスの時は付与されません。

format7_test.py
x = 100
y = 1.5
z = -300

print('xは{:+}。yは{:+}。zは{:+}。'.format(x,y,z))

出力結果

xは+100。yは+1.5。zは-300。

変数zの値はマイナスなので、自動判断によって+符号は付与されていません。

%を付与する

「'{:.n%}'.format(値)」と指定することで%表示が可能です。"n"には小数点以下の桁数を指定します。

format8_test.py
x = 1
y = 10

print('xは{:%}。yは{:%}。'.format(x,y))

出力結果

xは100.000000%。yは1000.000000%。

指定した値が100倍されて出力されています。これも、f文字列と同じです。
小数点以下の桁数を指定して、見やすくしましょう。

format8_test.py
x = 1
y = 10

print('xは{:.0%}。yは{:.0%}。'.format(x,y))

出力結果

xは100%。yは1000%。

出力結果から「'{:.n%}'」のnの値が、小数点以下の桁数指定となっていることがわかると思います。

数値のゼロ埋め方法

桁数を揃えるために、不足している分の桁をゼロで埋めて桁数を統一にしたい場合は、「'{:0=n}'.format(値)」と指定します。"n"には表示させたい桁数を指定します。

format9_test.py
x = 123
y = 45

print('xは{:0=8}。yは{:0=8}。'.format(x,y))

出力結果

xは00000123。yは00000045。

桁数指定を8に設定したので、不足している分はゼロで埋めて8桁で出力されています。

小数点を含んだ値のゼロ埋めについても、f文字列同様に小数点を含めて指定した桁数になるようにゼロ埋めされます。

format10_test.py
x = 0.123
y = 12.3

print('xは{:0=8}。yは{:0=8}。'.format(x,y))

出力結果

xは0000.123。yは000012.3。

桁数指定を8に設定しましたが、出力結果は小数点を含めて8桁になっています。

文字埋め方法

ゼロ埋め同様に、桁数を揃えるために不足している分の桁を、文字で埋めて桁数を統一させることも可能です。「'{:a>n}'.format(値)」と指定します。"a"には埋めたい文字を指定して、"n"には表示させたい桁数を指定します。

format11_test.py
x = 123
y = 45

print('xは{:X>8}。yは{:X>8}。'.format(x,y))

出力結果

xはXXXXX123。yはXXXXXX45。

表示位置の指定

右寄せや、中央揃えといった表示位置の指定も可能です。

右寄せ

「'{:>n}'.format(値)」と指定することで、右寄せで表示することができます。"n"には表示させたい桁数を指定します。

format12_test.py
name = '山田'
age = 25

print('私は{:>5}です。年齢は{:>5}歳です。'.format(name,age))

出力結果

私は   山田です。年齢は   25歳です。

nに5を指定したので、5桁の右寄せで表示されました。

左寄せ

「'{:<n}'.format(値)」と指定することで、左寄せで表示することができます。"n"には表示させたい桁数を指定します。

format13_test.py
name = '山田'
age = 25

print('私は{:<5}です。年齢は{:<5}歳です。'.format(name,age))

出力結果

は山田   です。年齢は25   歳です。

nに5を指定したので、5桁の左寄せで表示されました。

中央揃え

「'{:^n}'.format(値)」と指定することで、中央揃えで表示することができます。"n"には表示させたい桁数を指定します。

format14_test.py
name = '山田'
age = 25

print('私は{:^5}です。年齢は{:^5}歳です。'.format(name,age))

出力結果

私は 山田  です。年齢は 25  歳です。

nに4を指定したので、4桁の中央揃えで表示されました。

リスト・タプル・辞書の指定方法

formatメソッドでも、リスト・タプル・辞書を扱うことが可能です。

リスト

以下にリストを扱う際のサンプルコードを記述します。置換フィールドに「'{0[n]} {0[n]} {0[n]}'.format(リスト)」と指定します。"n"には要素のインデックス番号を指定します。全ての要素を取り出すには、「.format(*リスト)」のようにアスタリスク(*)を付与します。

format15_test.py
lst = [1,2,3,4,5]

print('リスト出力1:{0[0]}'.format(lst))
print('リスト出力2:{0[0]} {0[1]}'.format(lst))
print('リスト出力3:{} {} {} {} {}'.format(*lst))

出力結果

リスト出力1:1
リスト出力2:1 2
リスト出力3:1 2 3 4 5

複数のリストは指定する場合は、置換フィールドに紐付く番号をインデックスと合わせて指定します。コードは以下のとおりです。

format16_test.py
lst1 = [1,2,3,4,5]
lst2 = [5,6,7,8,9,10]

print('リスト出力:{0[0]}, {0[1]}, {0[2]}, {1[0]}, {1[1]}, {1[2]}'.format(lst1,lst2))

出力結果

リスト出力:1, 2, 3, 5, 6, 7

タプル

タプルの扱い方は、リスト同様です。

format17_test.py
tup = (1,2,3,4,5)

print('タプル出力1:{0[0]}'.format(tup))
print('タプル出力2:{0[0]} {0[1]}'.format(tup))
print('タプル出力3:{} {} {} {} {}'.format(*tup))

出力結果

タプル出力1:1
タプル出力2:1 2
タプル出力3:1 2 3 4 5

複数のタプルを指定する場合もリストの時同様に、置換フィールドに紐付く番号をインデックスと合わせて指定します。コードは以下のとおりです。

format18_test.py
tup1 = (1,2,3,4,5)
tup2 = (5,6,7,8,9,10)

print('タプル出力:{0[0]}, {0[1]}, {0[2]}, {1[0]}, {1[1]}, {1[2]}'.format(tup1,tup2))

出力結果

タプル出力:1, 2, 3, 5, 6, 7

辞書

辞書を扱う際は、キーを指定することが可能です。

format19_test.py
name_dict = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}

print('辞書出力1:{0[name]}'.format(name_dict))
print('辞書出力2:{0[name]} {0[mail]}'.format(name_dict))
print('辞書出力3:{} {} {}'.format(*name_dict))

出力結果

辞書出力1:山田
辞書出力2:山田 pythonlesson@gmail.com
辞書出力3:name TEL mail

複数の辞書を指定する場合はリストの時と同様に、置換フィールドに紐付く番号を辞書のキーと合わせて指定します。コードは以下のとおりです。

format20_test.py
name_dict_1 = {'name': '山田', 'TEL': '090-1234-5678','mail': 'pythonlesson@gmail.com'}
name_dict_2 = {'name': '田中', 'TEL': '080-8765-4321','mail': 'sample@gmail.com'}

print('辞書出力:{0[name]}, {0[TEL]}, {1[name]}, {1[TEL]}'.format(name_dict_1,name_dict_2))

出力結果

辞書出力:山田, 090-1234-5678, 田中, 080-8765-4321

波括弧の表示

波括弧{}を表示させたい場合は、表示させたい波括弧をさらに波括弧で囲んでエスケープすることで表示が可能になります。

format21test.py
name = '山田'
age = 25

print('私は{}です。年齢は{{}}歳です。'.format(name,age))

出力結果

私は山田です。年齢は{}歳です。

f文字列の時同様に波括弧をエスケープすると、その中の変数や式もエスケープされます。
変数の値も表示させるためには、波括弧を2回記述する必要があります。

format21_test.py
name = '山田'
age = 25

print('私は{}です。年齢は{{{}}}歳です。'.format(name,age))

出力結果

私は山田です。年齢は{25}歳です。

Lesson 5 Chapter 5
ファイルを読み書きする

Pythonでのファイルの読み書きについて解説します。このChapterでは、テキストファイルに対して読み書きを行う操作方法を身につけていきましょう。

ファイルオブジェクトについて

ファイルへの読み書きを行うためには、ファイルの読み書きが可能なオブジェクトであるファイルオブジェクトに対して操作を行います。
ファイルオブジェクトは準備されているわけではないので、ファイルを読み書きするために、まずは、ファイルオブジェクトを作成し、そのオブジェクトに対して読み書きの操作を行うことになります。

ファイルオブジェクトの作成

ファイルオブジェクトは、関数「open」を使用して作成します。構文は、「f = open(ファイル名/もしくはファイルパス,モード)」です。
これからopen関数を使用してファイルの読み書きを行っていきますが、その際には作成するパスに同一名称のファイルがないことを確認してから実行してください。同一名称のファイルが存在した場合、サンプルコードの実行によって更新してしまうので注意してください。

open関数の使い方

テスト用のテキストファイルを準備します。以下の内容で準備してください。

test.txt
aaa
bbb
ccc

読み込み用のファイルが準備できたら、open関数を使用してファイルオブジェクトを作成し、ファイルを読み込むコードを記述します。
構文は説明したとおり、「f = open(ファイル名/もしくはファイルパス,モード)」です。読み込みの場合は、モードに"r"を指定します。
処理の実行は最後に行うので、 まずは、コードの内容を理解しながら順番にコードを記述していきましょう。

file_open_.py
f = open('test.txt', 'r')

変数fには、open関数によって作成された読み込み可能なファイルオブジェクトが返り値として格納されます。
次に、作成したオブジェクトに対して操作を行うコードを記述します。ファイルオブジェクトを読み込むメソッド「read」を記述します。メソッドは、オブジェクトに対する手続きであると覚えてください。

file_open_.py
f = open('test.txt', 'r')
f.read()

ファイルオブジェクトを読み込んだ結果を画面出力するためのprint関数を記述します。

file_open_.py
f = open('test.txt', 'r')
print(f.read())

最後にメソッド「close」で、読み込んだファイルオブジェクトのCLOSE処理を行います。CLOSE処理を行わないと、メモリを使用した状態のままになります。
ExcelやPowerPointといったファイルを沢山開くと、画面にいくつものウィンドウが表示さると思いますが、そのような状態になってしまうとイメージしてください。必ず、最後にCLOSE処理が必要になります。

file_open_.py
f = open('test.txt', 'r')
print(f.read())
f.close()

ここまでのコードを書き終えたら、プログラムを実行しましょう。最初に作成したテスト用のテキストファイルの内容が表示されます。

出力結果

aaa
bbb
ccc

このように、ファイルの読み書きを行うためには、ファイルオブジェクトを作成し、それに対して操作を行います。
読み込みで使用したモードは"r"でしたが、それ以外にも下記の表のとおり書き込みや追加のモードも用意されています。読み込み以外のモードについては、以降のサンプルコード内で解説していきます。

モード 説明
r 読み込み ※デフォルトは読み込み
w 書き込み
a 追加
r+ 読み込み、書き込み
w+ 書き込み、読み込み
a+ 追加、読み込み

withステートメント

ファイルオブジェクトをOPENした際は、closeメソッドによるCLOSE処理が必要になります。逆に、CLOSE処理を忘れた場合は、ファイルオブジェクトはOPEN状態のままであり、メモリを使用し続けます。
このようなことを避けるために、withステートメントを使用してファイルオブジェクトの操作を行います。
withステートメントは、ファイルオブジェクトに対する処理が終了した時点で、CLOSE処理を実行してくれます。つまり、「f.close()」の記述が不要となり、CLOSE処理を書き忘れる心配がなくなります。
ここからは、withステートメントを用いてサンプルコードを記述していきます。

withステートメントの使い方

最初に実行したテスト用テキストファイルを読み込む処理を、withステートメントを使用したコードに書き換えてみましょう。
構文は、「with open(ファイル名/もしくはファイルパス) as 変数名:」です。

file_open2_.py
with open('test.txt', 'r') as f:
    contents = f.read()
    print(contents)

出力結果

aaa
bbb
ccc

出力結果だけではわかりませんが、withステートメントを使用したことで、CLOSE処理の記述が無くても、処理の最後にファイルオブジェクトをきちんとCLOSE処理したことになります。

ファイルの読み込み

ここまでは、ファイル操作についての概要を解説してきました。これからは、具体的なファイル操作を行っていきましょう。

まずは、読み込み操作から行っていきます。テスト用テキストファイルを以下のように修正して準備してください。

test.txt
Hello World
Python_Lesson_Chapter5
File read test

サイズを指定して読み込む

readメソッドに、読み込むサイズを指定することができます。
「.read(5)」と指定して実行してみましょう。

file_read_.py
with open('test.txt', 'r') as f:
    contents = f.read(5)
    print(contents)

出力結果

Hello

読み込むサイズを変更してみます。

file_read2_.py
with open('test.txt', 'r') as f:
    contents = f.read(20)
    print(contents)

出力結果

Hello World
Python_L

一行のみを読み込む

メソッド「readline」を使用して、一行だけを読み込むことが可能です。

file_read3_.py
with open('test.txt', 'r') as f:
    contents = f.readline()
    print(contents)

出力結果

Hello World
                    

改行が含まれて出力されます。

ファイルの書き込み

open関数のモードを"w"に指定することで、書き込み処理が可能になります。書き込みモードは、新規ファイルを作成して書き込みを行います。このため、すでに存在するファイルを書き込みモードで開いた場合は、中身を空にしてしまうので注意が必要です。単なる書き込みではなく、新規ファイルを作成して書き込むといったことを覚えてください。
まずは、以下のコードで書き込みモードの動作を確認しましょう。
コード内で作成するファイルと同一名称のファイルがある場合は、上書きしてしまうのでファイル名をリネームするか、もしくは別の格納先へ退避しておきましょう。

open関数のモードを"w"として、メソッド「write」の引数に書き込みたい値を指定します。

file_write_.py
with open('write_test.txt', 'w') as f:
    f.write('Print Test')

「write_test.txt」ファイルが作成されているはずです。中身を確認しましょう。

write_test.txt
Print Test

writeメソッドの引数に指定した文字列が書き込まれました。

次に、writeメソッドの引数を別の文字列に変更して、再度open関数のモードを"w"で開いて処理を実行してみましょう。

file_write2_.py
with open('write_test.txt', 'w') as f:
    f.write('Hello World')

ファイルの中身を再度確認します。

write_test.txt
Hello World

最初に書き込んだ、"Print Test"が上書きされていることが確認できます。open関数のモード"w"は新規ファイルを作成したうえで、文字を書き込むことに注意してください。

読み込み時に使用したreadメソッドを、書き込みモードで使用した際の動作を確認しましょう。

file_write3_.py
with open('write_test.txt', 'w') as f:
    contents = f.read()
    print(contents)

出力結果

io.UnsupportedOperation: not readable

処理がエラーになりました。
このように、読み込みを行うためには読み込み用の、書き込むためにはそれ用のファイルオブジェクトをopen関数のモードで指定して作成する必要があります。

ファイルへの追加

モード"w"は新規ファイルを作成し書き込みを行いましたが、モード"a"を使用することで、ファイルへの更新処理が可能です。

モード"w"と同じwriteメソッドを使用して追加が可能です。 テスト用テキストファイルを以下のように新規作成して準備してください。
append.txt
append test1
append test2

テスト用のファイルが準備できたら、open関数で作成した追加可能なファイルオブジェクトに対して追加処理を行うコードを記述し実行しましょう。

file_append_.py
with open('append.txt', 'a') as f:
    f.write('append test3')

「append.txt」ファイルの中身を確認しましょう。

append.txt
append test1
append test2append test3

2行目の"append test2"に続けて追加されました。改行して追加したい場合は、writeメソッドの引数指定時に改行コードも加える必要があります。改行コードは、バックスラッシュ(\)に"n"です。
改行して追加するコードを記述しましょう。

file_append2_.py
with open('append.txt', 'a') as f:
    f.write('\nappend test4')

「append.txt」ファイルの中身を確認しましょう。

append.txt
append test1
append test2append test3
append test4

ファイルの読み込み・書き込み

ファイルの書き込みの際に解説したとおり、モード"w"で作成した書き込み用のファイルオブジェクトへは、readメソッドを使用した読み込みはできませんでした。勿論その逆も同様で、読み込み用のファイルオブジェクトへは、writeメソッドを使用した書き込み処理はできません。
どちらも行いたい場合に、都度それぞれのファイルオブジェクトを作成するコードを記述することは手間になります。
そこで、それぞれを同時に実行可能とするモードが用意されています。

ファイルの読み込み・書き込み

まずは、ファイルを読み込んでから書き込みを可能とする、モード"r+"のコードを記述します。

テスト用テキストファイルを以下のように新規作成して準備してください。

read_write.txt
read test

テスト用のファイルが準備できたら、open関数を使用してファイルオブジェクトを作成し、読み込み・書き込み処理を行うコードを記述します。

read_write_.py
with open('read_write.txt', 'r+') as f:
    contents = f.read()
    print(contents)
    f.write('\nwrite test2')

出力結果

read test1

書き込みを行う前のファイルの内容が、print関数によって出力されました。
次に、ファイルの中身を再度確認します。

read_write.txt
read test1
write test2

writeメソッドの処理が正常に実行され、引数に指定した文字列が追加されたことが確認できます。

参考までに、モード"r+"を使用しない場合のコードを記述して、モード"r+"の利便性を確認しましょう。

read_write_.py
with open('read_write.txt', 'r') as f:
    contents = f.read()
    print(contents)

with open('read_write.txt', 'a') as f:
    f.write('\nwrite test')

いかがでしょうか。コード量が増えているのが一目瞭然です。

ファイルの書き込み・読み込み

ファイルの書き込みを行ってから読み込みを実行するモードが"w+"です。以下のコードを記述して実行してみましょう。

write_read.py
with open('write_read.txt', 'w+') as f:
    f.write('write_read test')
    contents = f.read()
    print(contents)

出力結果に何も出力されなかったはずです。これは、書き込み後の最終行から出力が開始されているためです。書き込んだ内容を出力するためには、最初の行を読み込み直す処理が必要です。
これには、メソッド「seek」を使用して引数にゼロを指定することで、一行目から読み込み直します。

write_read.py
with open('write_read.txt', 'w+') as f:
    f.write('write_read test')
    f.seek(0)
    contents = f.read()
    print(contents)

出力結果

write_read test

書き込んだ内容が出力できたはずです。モード"w+"が書き込み後に読み込み可能であることが確認できました。

ファイルの追加・読み込み

追加にはモード"a+"が準備されています。これは、ファイルの追加・読み込みを行うモードです。

テスト用テキストファイルを以下のように新規作成して準備してください。

append_read.txt
append test1
append test2
append test3

テスト用のファイルが準備できたら、open関数を使用してファイルオブジェクトを作成し、追加・読み込み処理を行うコードを記述します。

append_read.py
with open('append_read.txt', 'a+') as f:
    f.write('\nread test1')
    f.seek(0)
    contents = f.read()
    print(contents)

出力結果

append test1
append test2
append test3
read test1

問題なく出力されたはずです。次に、ファイルの中身も確認してみましょう。writeメソッドの引数に指定した文字列が改行含めて問題なく追加されているはずです。

Lesson 5 Chapter 6
jsonによる構造化されたデータの保存

Web APIは、プログラムを用いてWebサービスを操作するための方法ですが、Web上でデータをやり取りするためには、決まったルールで送受信をしなければなりません。そこでルールに則ったデータ、すなわち構造化されたデータが必要になります。
このChapterでは、構造化されたデータの一つであり、Web APIなどでデータのやり取りをする際のフォーマットとして多く利用される「json」のデータ保存方法について解説します。

jsonとは

jsonとは、「JavaScript Objective Notation」の略で、JavaScriptのために作られたデータの表現形式です。現在では、様々な言語で利用されることが多くなり、冒頭で解説したとおり、Web APIを使用したシステム間通信時のデータフォーマットとしても用いられます。

jsonのデータフォーマット形式

jsonの基本形式は、{"キー1":値1, "キー2":値2, ...}となり、Pythonの辞書によく似ています。ただし、キーはダブルクォーテーション(")で囲む必要があり、値で文字列を扱う際もダブルクォーテーションで囲みます。Pythonでは、シングルクォーテーションの利用も可能でしたが、jsonはダブルクォーテーションに限られるので注意してください。
ファイル拡張子は、「.json」です。jsonは、キーと値によって構造化されたデータを作成することができます。
構造化されたjsonのデータとは、以下のようなデータです。ユーザ情報の保持を想定した、json形式のファイルを作成しますので、その構造を理解してください。

sample.json
{
  "name": "山田",
  "address": "渋谷区",
  "TEL": "090-1234-5678",
  "mail": "yamada_sample@gmail.com"
}

このように、Pytonの辞書型によく似ていることがわかると思います。
複数の情報を保持する場合は、全体を波括弧{}か角括弧[]で囲います。
複数ユーザ情報の保持を想定した場合は、以下のような記述になります。

sample.json
{
  "ID1": {
    "name": "山田",
    "address": "渋谷区",
    "TEL": "090-1234-5678",
    "mail": "yamada_sample@gmail.com"
  },
  "ID2": {
    "name": "鈴木",
    "address": "品川",
    "TEL": "080-8765-4321",
    "mail": "suzuki_sample@gmail.com"
  },
  "ID3": {
    "name": "田中",
    "address": "新宿区",
    "TEL": "090-5377-2188",
    "mail": "tanaka_sample@gmail.com"
  }
}

jsonをPythonで扱う方法

Pythonでjsonを扱うためには、まず、「jsonモジュール」が必要になります。モジュールとは、Pythonのコードが纏められたファイルです。関数が沢山纏められている部品と捉えてください。Pythonには多くのモジュールがあり、目的や種類によって分類されています。
今回はjsonを扱うことが目的なので、それ用のモジュールを準備する必要があります。
モジュールは、import文で取り込むことで使用可能になります。以下のコードを記述することで、jsonモジュールが使用可能になります。

import json

json形式の保存方法

実際にjson形式で保存してみましょう。
順序立ててコードを記述していきます。まずは、辞書型のデータを準備します。

json_test.py
user_info = {'name': '山田', 'TEL': '090-1234-5678', 'mail': 'yamada_sample@gmail.com'}

次に、jsonモジュールをインポートします。

json_test.py
user_info = {'name': '山田', 'TEL': '090-1234-5678', 'mail': 'yamada_sample@gmail.com'}

import json #jsonモジュールのインポート

最後にwithステートメントを用いたファイルへの書き込み処理を記述しますが、json形式で保存するためには、辞書型からjson形式に変換する必要があります。json形式への変換は、jsonモジュールで使用可能なdump関数で変換が可能です。
構文は、「json.dump(変換対象オブジェクト, 書き出し先ファイルオブジェクト)」です。
以下のコードを記述した後に、実行してみましょう。

json_test.py
user_info = {'name': '山田', 'TEL': '090-1234-5678', 'mail': 'yamada_sample@gmail.com'}

import json #jsonモジュールのインポート

file_path = './UserInfo.json'

with open(file_path, 'w') as f:
    json.dump(user_info, f) #json形式に変換

ファイル「UserInfo.json」が作成されたはずです。中身を確認しましょう。

UserInfo.json
{"name": "\u5c71\u7530", "TEL": "090-1234-5678", "mail": "yamada_sample@gmail.com"}

Pythonの辞書型を定義する際に使用したシングルクォーテーションが、json形式のダブルクォーテーションに変わっていることで、正常に辞書型からjson形式に変換されたことが確認できます。
しかし、キーがnameの"山田"がUnicodeという文字コードで変換されてしまいました。
日本語の全角文字など文字コードが非ASCIIコードの場合は、json形式ではUnicodeに変換されます。これを避けるために、dump関数の引数に「ensure_ascii=False」を指定することで、日本語の全角文字などはそのままとなります。
引数を追加したコードに修正して実行してみましょう。

json_test.py
user_info = {'name': '山田', 'TEL': '090-1234-5678', 'mail': 'pythonlesson@gmail.com'}

import json #jsonモジュールのインポート

file_path = 'UserInfo.json'

with open(file_path, 'w') as f:
    json.dump(user_info, f, ensure_ascii=False) #json形式に変換

再度ファイルの中身を確認しましょう。引数「ensure_ascii=False」により、日本語のままjson形式に変換されているはずです。

UserInfo.json
{"name": "山田", "TEL": "090-1234-5678", "mail": "pythonlesson@gmail.com"}

jsonファイルの読み取り・更新・保存

先程は、辞書型からjson形式に変換してファイルへ保存しましたが、今度は、jsonファイルを読み取り、データの更新後に保存する方法を解説します。
まずは、読み取り用のjsonファイルを作成しましょう。拡張子は「.json」です。

sample.json
{
  "ID1": {
    "name": "山田",
    "address": "渋谷区",
    "TEL": "090-1234-5678",
    "mail": "yamada_sample@gmail.com"
  },
  "ID2": {
    "name": "鈴木",
    "address": "品川",
    "TEL": "080-8765-4321",
    "mail": "suzuki_sample@gmail.com"
  },
  "ID3": {
  "name": "田中",
  "address": "新宿区",
  "TEL": "090-5377-2188",
  "mail": "tanaka_sample@gmail.com"
  }
}

jsonファイルの準備ができたら、プログラムを作成していきましょう。
withステートメントを使用して、jsonファイルを読み取るコードを記述します。
jsonファイルを読み取るには、jsonモジュールで使用可能なload関数を使用し、引数に読み取るファイルを指定します。load関数で読み取ることで、辞書型としてデータを取得します。json形式のデータから、Pythonでも扱える辞書型に変換することで、データの更新が可能になります。

json_test2.py
import json #jsonモジュールのインポート

file_path = './sample.json'

with open(file_path, 'r') as f:
    json_data = json.load(f) #辞書型で読み込み

次に、キーを指定して要素を変更する処理を追加します。

json_test2.py
import json #jsonモジュールのインポート

file_path = './sample.json'
key1 = 'ID3'
key2 = 'name'

with open(file_path, 'r') as f:
    json_data = json.load(f) #辞書型で読み込み
    json_data[key1][key2] = '木村'

最後に更新した辞書をdump関数を使用して、json形式に戻してファイルを上書き保存する処理を記述します。全てのコードが記述できたら実行して、更新されたファイルの中身を確認してみましょう。

json_test2.py
import json #jsonモジュールのインポート

file_path = './sample.json'
key1 = 'ID3'
key2 = 'name'

with open(file_path, 'r') as f:
    json_data = json.load(f) #辞書型で読み込み
    json_data[key1][key2] = '木村'

with open(file_path, 'w') as f:
    json.dump(json_data, f, ensure_ascii=False) #json形式に変換
sample.json
{"ID1": {"name": "山田", "address": "渋谷区", "TEL": "090-1234-5678", "mail": "yamada_sample@gmail.com"}, "ID2": {"name": "鈴木", "address": "品川", "TEL": "080-8765-4321", "mail": "suzuki_sample@gmail.com"}, "ID3": {"name": "木村", "address": "新宿区", "TEL": "090-5377-2188", "mail": "tanaka_sample@gmail.com"}}

ID3のname:"田中"が、"木村"へ更新されダブルクォーテーションで囲まれたjson形式のファイルとして保存されていますが、改行やインデントが無くなり、データが一行で構成されて見ずらくなっています。
json形式のファイルに保存する際に、改行やインデントを付与して保存するには、dump関数の引数に「indent=n」を指定します。"n"にはインデント数を指定できます。
以下のコードのように、引数indent=nを追加して、再度処理を実行してみましょう。
処理結果の内容がわかりやすいように、今度はID1のname:"山田"を更新してみます。

json_test2.py
import json #jsonモジュールのインポート

file_path = './sample.json'
key1 = 'ID1'
key2 = 'name'

with open(file_path, 'r') as f:
    json_data = json.load(f) #辞書型で読み込み
    json_data[key1][key2] = '村田'

with open(file_path, 'w') as f:
    json.dump(json_data, f, indent=2, ensure_ascii=False) #json形式に変換

処理が完了したら、ファイルの中身を確認します。

sample.json.json
{
  "ID1": {
    "name": "村田",
    "address": "渋谷区",
    "TEL": "090-1234-5678",
    "mail": "yamada_sample@gmail.com"
  },
  "ID2": {
    "name": "鈴木",
    "address": "品川",
    "TEL": "080-8765-4321",
    "mail": "suzuki_sample@gmail.com"
  },
  "ID3": {
    "name": "木村",
    "address": "新宿区",
    "TEL": "090-5377-2188",
    "mail": "tanaka_sample@gmail.com"
  }
}

綺麗に整形されて保存できていることが確認できます。