スッキリわかるPython入門 第2版でPythonを勉強しました。
いい機会なのでPythonについて諸々まとめておきたいと思います。
スッキリシリーズはJava入門を昔購入し保有していました。オブジェクト指向についてRPGの概念と組み合わせて分かりやすく説明してくれたので仕事の勉強をする上でかなり助かった記憶があります。
今回はそのPython入門版を読んでみました。
Pythonに関しては2系が主流のときから使っていましたが、元々CやJavaなど他のプログラミング言語を知っていたことや、コードで実現したいことで分からないことは都度調べれば何とかなっていました。
そろそろきちんと体系的に学びたいと思いPython言語について説明している本を読んでみることにしました。
結果としては読んでみて正解でした。
tupleやlistの使い分けや関数の応用テクニックなど図解と共に説明されており非常に分かりやすかったです。
ほぼ自分用になってしまいますが、Pythonに関してまとめておこうと思います。
本記事で利用しているPythonのバージョン
python3 -V
Python 3.8.13
Python3.8.13になります。
ちなみに執筆時点だと2023-03-08 Python 3.12.0 alpha 6 releasedが最新版のようです。
Pythonでゴリゴリ処理を書く場合、バージョンごとの違いを調べておいた方が良いかも知れません。(私はPython自体のバージョンの違いにライブラリのインストール以外で困ったことはなかったのですが、使っているPython標準ライブラリの挙動が変わる場合があるようです。)
例えばos.pathの挙動がValueErrorの代わりにFalseを返却するように3.8から変わったようです。
os.path functions that return a boolean result like exists(), lexists(), isdir(), isfile(), islink(), and ismount() now return False instead of raising ValueError
引用: https://docs.python.org/3/whatsnew/3.8.html#os-path
皆さん大体Python3.6以上を使う機会が多いと思うので、各バージョンでの変更点をまとめてあるwhatsnewページへのリンクを記載しておきます。
・https://docs.python.org/3/whatsnew/3.6.html
・https://docs.python.org/3/whatsnew/3.7.html
・https://docs.python.org/3/whatsnew/3.8.html
・https://docs.python.org/3/whatsnew/3.9.html
・https://docs.python.org/3/whatsnew/3.10.html
・https://docs.python.org/3/whatsnew/3.11.html
Python Enhancement Proposals (PEPs)
Pythonに関する規約や提案がたくさんまとめられているPEP indexというリンク集が公式に存在します。
その中でもPEP8はPythonのコーディング規約について書かれていて勉強になりました。(日本語版はreadthedocsにありました。)
よく読んでみると空白入れない方がいいところにいれてしまうとかはやりがちかも知れません 汗 リーダブルコードという本を思い出しました。
PythonでPrintのやり方を色々まとめてみた
まずは基本の出力(print)の方法をまとめてみました。
name="ヒノマルク"
height=180.5
weight=80
age=38
値はもちろん適当です 笑
単純に羅列したい場合
print(name,height,weight,age)
ヒノマルク 180.5 80 38
単純に羅列したい場合 (コンマ区切り)
print(name,height,weight,age,sep=",")
ヒノマルク,180.5,80,38
文章で表示 (formatメソッド) ※ 体重を小数点1桁表示ver
### 文章で表示 (formatメソッド) ※ 体重を小数点1桁表示ver
print("{}の身長は{}cmで、体重は{:.1f}kgで、年齢は{}歳です。".format(name,height,weight,age))
ヒノマルクの身長は180.5cmで、体重は80.0kgで、年齢は38歳です。
文章で表示 (Formatted String Literals known as f-strings) ※ 体重を小数点1桁表示ver
print(f"{name}の身長は{height}cmで、体重は{weight:.1f}kgで、年齢は{age}歳です。")
ヒノマルクの身長は180.5cmで、体重は80.0kgで、年齢は38歳です。
先頭の「f」は大文字でも小文字でもOKですが、Python3.6以上でないと使えません。
Pythonリストの使い方
基本のリストの使い方になります。私は一番よく使っていると思います。
python_list=[1,2,3,4,5,6,7,8,9,10]
インデックスでリストの要素を参照する
インデックスは0から開始します。そのためインデックスの番号は今回の例だと9までしか存在しません。10番目のインデックスを参照しようとするとIndexErrorになります。
# 0番目
print(python_list[0])
# 5番目
print(python_list[5])
# エラーになる
print(python_list[10])
1 6 --------------------------------------------------------------------------- IndexError Traceback (most recent call last) Cell In[28], line 3 1 print(python_list[0]) 2 print(python_list[5]) ----> 3 print(python_list[10]) IndexError: list index out of range
リストへ要素の追加・削除・変更
# リストに11を追加
python_list.append(11)
print(python_list)
# リストから5を削除
python_list.remove(5) #または del python_list[4]で5の要素を削除する
print(python_list)
# リストの最後の値を5に変更 (11->5に変更)
python_list[-1] = 5
print(python_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [1, 2, 3, 4, 6, 7, 8, 9, 10, 11] [1, 2, 3, 4, 6, 7, 8, 9, 10, 5]
スライスによる要素の参照
numpyやpandasで使ってる方も多いのではないでしょうか?リストでも出来るようです。
print(python_list[3:]) # index >= 3
print(python_list[:3]) # index < 3
print(python_list[3:5]) # index 3 <= index < 5
[4, 6, 7, 8, 9, 10, 5] [1, 2, 3] [4, 6]
for loopによるリストの要素へのアクセス
for i in python_list:
print(i)
1 2 3 4 6 7 8 9 10 5
Pythonディクショナリの使い方
まずはディクショナリ(辞書)を作成します。オーソドックスに各教科の成績のディクショナリを作成しました。
python_dict={'名前':'ヒノマルク','国語':80,'数学':30,'英語':90,'理科':20,'社会':70}
print(python_dict)
{'名前': 'ヒノマルク', '国語': 80, '数学': 30, '英語': 90, '理科': 20, '社会': 70}
キーを選択しディクショナリの要素(Value:値)を参照する
print(python_dict['国語'])
print(python_dict['社会'])
80 70
ディクショナリのキー・バリュー・アイテムの値を出力する
print(python_dict.keys())
print(python_dict.values())
print(python_dict.items())
dict_keys(['名前', '国語', '数学', '英語', '理科', '社会']) dict_values(['ヒノマルク', 80, 30, 90, 20, 70]) dict_items([('名前', 'ヒノマルク'), ('国語', 80), ('数学', 30), ('英語', 90), ('理科', 20), ('社会', 70)])
ディクショナリへ要素の追加・削除・変更
# 体育を追加
python_dict["体育"] = 100
print(python_dict)
# 社会を削除
del python_dict["社会"]
print(python_dict)
# 体育の値を変更
python_dict['体育'] = 50
print(python_dict)
{'名前': 'ヒノマルク', '国語': 80, '数学': 30, '英語': 90, '理科': 20, '社会': 70, '体育': 100} {'名前': 'ヒノマルク', '国語': 80, '数学': 30, '英語': 90, '理科': 20, '体育': 100} {'名前': 'ヒノマルク', '国語': 80, '数学': 30, '英語': 90, '理科': 20, '体育': 50}
Valueの合計値を出してみる
Valueが数値のみの情報であればsum(python_dict.values())で270という合計値が出せるが、今回は名前もディクショナリに含めてしまっているのでエラーになる。
解決方法として、intのみ選択して合計していくか、strを含まない新しい辞書をDict Comprehensionsで作成し合計値を出すかの方法があるので試してみる。
※ 分かりやすいように後者の方法は新しい辞書の中身をアウトプットしている。
# エラーになる (strを合算しようとするため)
try:
print(sum(python_dict.values()))
except Exception as err:
print(err)
# valueがintの場合、合計していく
print(sum(v for v in python_dict.values() if isinstance(v, int)))
# valueがint以外のキーは除外する。sum({}.values())で合計が出る
print({key: python_dict[key] for key in python_dict if isinstance(python_dict[key], int)})
# valueがint以外のキーの値は0に置換する。sum({}.values())で合計が出る
print({key: python_dict[key] if isinstance(python_dict[key], int) else 0 for key in python_dict})
unsupported operand type(s) for +: 'int' and 'str' 270 {'国語': 80, '数学': 30, '英語': 90, '理科': 20, '体育': 50} {'名前': 0, '国語': 80, '数学': 30, '英語': 90, '理科': 20, '体育': 50}
for loopによるディクショナリ要素へのアクセス
Keyのみ、Valueのみ、Key,Value両方の値を取り出しながらループする方法をそれぞれ紹介します。
for key,val in python_dict.items():
print(key,val)
print("---")
for key in python_dict.keys():
print(key)
print("---")
for val in python_dict.values():
print(val)
名前 ヒノマルク 国語 80 数学 30 英語 90 理科 20 体育 50 --- 名前 国語 数学 英語 理科 体育 --- ヒノマルク 80 30 90 20 50
要素の追加・変更・削除を防げるタプル(Tuple)
変更できないリストのようなものという認識です。中身を誤って書き換えないようにしたい場合などに使えます。当然appendやremoveメソッドはありません。
python_tuple=(1,2,3,4,5)
print(python_tuple[0])
print(python_tuple[3])
1 4
try:
python_tuple[3] = 10
except Exception as err:
print(err)
try:
del python_tuple[3]
except Exception as err:
print(err)
'tuple' object does not support item assignment 'tuple' object doesn't support item deletion
無事?エラーになりました。
print(type((1)))
print(type((1,)))
class 'int'> class 'tuple'>
「,」がないとタプルにならないことに注意が必要です。
要素の重複を許さないセット(Set)
私はよく分析やデータ加工するときに重複を除外したい場合に使うことがあります。
python_set={1,2,3,4,5}
print(type(python_set))
class 'set'>
python_set.add(6)
python_set.add(6)
python_set.add(6)
python_set.add(6)
python_set.add(6)
python_set.add(6)
print(python_set)
{1, 2, 3, 4, 5, 6}
1つしか追加されていません。
集合演算
セットだと集合演算が出来るようです。具体的には2つのセットから和集合・積集合・差集合・対象差を求めることが出来ます。
python_set1={1,2,3,4,5}
python_set2={4,5,6,7,8}
print("和集合:", python_set1 | python_set2)
print("積集合:", python_set1 & python_set2)
print("差集合:", python_set1 - python_set2)
print("対象差:", python_set1 ^ python_set2)
和集合: {1, 2, 3, 4, 5, 6, 7, 8} 積集合: {4, 5} 差集合: {1, 2, 3} 対象差: {1, 2, 3, 6, 7, 8}
・和集合はpython_set1とpython_set2のどちらかに存在している値を演算
・積集合はpython_set1とpython_set2の両方に存在している値を演算
・差集合はpython_set1にしかない値を演算
・対象差はpython_set1とpython_set2両方に存在している値は除外したものを演算 (つまり和集合 - 積集合)
その他のcollections
何かしらの実装や処理を書いているとList・Dictionary・Tuple・Setでは少し痒い所に手が届かない状況が出てくる場合があります。
その場合はPythonビルトインのコンテナデータ型が使えるかも知れません。
This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict, list, set, and tuple. 引用: https://docs.python.org/3/library/collections.html
・namedtuple()
・deque
・ChainMap
・Counter
・OrderedDict
・defaultdict
・UserDict
・UserList
・UserString
Counterを使ってみる
from collections import Counter
fruits_list=['イチゴ', 'バナナ', 'イチゴ', 'オレンジ', 'オレンジ', 'オレンジ']
cnt = Counter()
for fruit in fruits_list:
cnt[fruit] += 1
print(cnt)
Counter({'オレンジ': 3, 'イチゴ': 2, 'バナナ': 1})
簡単ですね。
次にCounterを使わない場合どういう書き方になるのか見てみます。
fruit_dict={}
for key in fruits_list:
try:
fruit_dict[key] = fruit_dict[key] + 1
except KeyError as err:
print(f"Unexpected {err=}, {type(err)=}")
fruit_dict[key] = 1
print(fruit_dict)
Unexpected err=KeyError('イチゴ'), type(err)=class 'KeyError'> Unexpected err=KeyError('バナナ'), type(err)=class 'KeyError'> Unexpected err=KeyError('オレンジ'), type(err)=class 'KeyError'> {'イチゴ': 2, 'バナナ': 1, 'オレンジ': 3}
結果は同じですが、記述量が多くちょっと複雑ですね。
ちなみに色々な書き方があると思います。もっと簡単に書けないかChatGPTにも聞いてみました。
fruit_dict = {}
for key in fruits_list:
fruit_dict[key] = fruit_dict.get(key, 0) + 1
print(fruit_dict)
{'イチゴ': 2, 'バナナ': 1, 'オレンジ': 3}
dict.get() メソッドを使用することで、try-except ブロックを使用する必要がなくなり、より簡潔なコードになりました。get() メソッドは、辞書に指定されたキーが存在する場合にはその値を返し、存在しない場合にはデフォルト値を返します。この場合、get() メソッドは、キーが存在しない場合には 0 を返し、既に存在する場合には現在の値を返します。その後、各果物の出現回数を数え上げて、fruit_dict に追加します。最終的に fruit_dict を出力します。
引用: ChatGPT
ふむふむそうなのね。Counterいらないかもな。。これからはChatGPT先生から学ぼうと思います 笑
繰り返し処理の制御 (break・continue・pass)
・breakは以降の繰り返し処理を全て中断
・continueは今の処理を中断し次の繰り返し処理へ進む
・passは何もしない
という意味になります。
実際に処理を書いてみて挙動を確かめてみましょう。
# 1から10まで繰り返す処理を考える
for i in range(1,10+1,1):
print(i)
print("\n---break---")
# 5回目のループでbreak
for i in range(1,10+1,1):
if i == 5:
break
print(i)
print("\n---continue---")
# 5回目のループでcontinue
for i in range(1,10+1,1):
if i == 5:
continue
print(i)
print("\n---pass---")
# 5回目のループでpass
for i in range(1,10+1,1):
if i == 5:
pass
print("pass")
print(i)
1 2 3 4 5 6 7 8 9 10 ---break--- 1 2 3 4 ---continue--- 1 2 3 4 6 7 8 9 10 ---pass--- 1 2 3 4 pass 5 6 7 8 9 10
私はデータ加工している時に1行ずつ処理しているときはcontinueを使うことがなぜか多いです 笑
Pythonでの関数の使い方のまとめ
一番まとめておきたかった内容が関数になります。def 関数名(引数1,引数2):と書きますが引数の設定方法などやり方が複数あります。
# 足し算関数
def addition(a,b):
return a+b
addition(1,2)
3
1足す2は3なので、3が返ってきます。とても簡単です 笑
通常戻り値は1つしか選択できません。
返却値をタプルにすると複数の値を返すことが出来る
戻り値は1つしか返却できませんが、タプルにまとめることによって複数の値を返却することが可能になります。
また戻り値であるタプルをアンパックすることによって、2つの変数を作成することも出来ます。
便利なので覚えておいて損はないです。
# 足し算と掛け算の結果を返す関数
def addition_and_multiplication(a,b):
return (a+b,a*b) #タプルにすることによって戻り値は1つ
# タプルが返ってくる
print(addition_and_multiplication(1,2),type(addition_and_multiplication(1,2)))
# タプルをアンパック
a,b=addition_and_multiplication(1,2)
print(f"タプルのアンパック: 足し算={a} 掛け算={b}")
(3, 2) class 'tuple'> タプルのアンパック: 足し算=3 掛け算=2
関数の引数の設定方法 (デフォルト引数・キーワード指定・可変長引数)
各引数の値が分かりやすいように関数を変更
def addition(a,b,c):
return f"(a={a})+(b={b})+(c={c})={a+b+c}"
print(addition(1,2,3))
(a=1)+(b=2)+(c=3)=6
まずは、値を省略してもOKなデフォルト引数です。
# デフォルト引数
def addition(a,b,c=10):
return f"(a={a})+(b={b})+(c={c})={a+b+c}"
print(addition(1,2))
(a=1)+(b=2)+(c=10)=13
第三引数にc=10をデフォルト値として入力しておきます。
そうすると関数を呼ぶ時に指定しなくても自動でc=10を入力してくれます。
次はキーワード指定です。これは例えばbとcをデフォルト引数にしていた場合にcの値だけを変更したい場合に使えます。
言葉だけでは伝わらないと思うので実例を見てみましょう。
# キーワード指定
def addition(a,b=5,c=10):
return f"(a={a})+(b={b})+(c={c})={a+b+c}"
print(addition(1,c=3))
(a=1)+(b=5)+(c=3)=9
bはデフォルト値でいいのだけど、cだけ変更したい場合に使えます。
def addition(a,b,c,num_tuple=()):
return f"(a={a})+(b={b})+(c={c})+(num_tuple={num_tuple})={a+b+c+sum(num_tuple)}"
print(addition(1,2,3,(5,5)))
(a=1)+(b=2)+(c=3)+(num_tuple=(5, 5))=16
想定通りです。
# 変数の前に*を追加するとタプルの可変長引数になる
def addition(a,b,c,*num_tuple):
return f"(a={a})+(b={b})+(c={c})+(num_tuple={num_tuple})={a+b+c+sum(num_tuple)}"
print(addition(1,2,3,5,5,3,3))
(a=1)+(b=2)+(c=3)+(num_tuple=(5, 5, 3, 3))=22
特に引数でタプルを投入しなくても勝手に第四引数以降をタプルとして認識してくれています。
他にもタプルではなく、ディクショナリとして読み込むことも出来ます。
# 変数の前に**を追加するとディクショナリの可変長引数になる
def addition(a,b,c,**num_dict):
return f"(a={a})+(b={b})+(c={c})+(num_tuple={num_dict})={a+b+c+sum(num_dict.values())}"
print(addition(1,2,3,d=5,e=5,f=3))
(a=1)+(b=2)+(c=3)+(num_dict={'d': 5, 'e': 5, 'f': 3})=19
色々な方法があるんですね。
シャローコピーとディープコピーの確認
長年この2つの言葉には苦しめられてきました 笑 今日で決着をつけたいと思います。
シャローコピーは、元のオブジェクトの参照をコピーする方法です。新しいオブジェクトを作成しますが、元のオブジェクトと同じメモリ領域を共有します。そのため片方の値を変更するともう片方にも影響が出ます。
一方でディープコピーは、元のオブジェクトの全ての値をコピーする方法です。新しいオブジェクトを作成し、元のオブジェクトとは異なるメモリ領域を持ち独立しています。したがって片方の値を変更しても、もう片方には影響がありません。
list_moto = [1, 2, 3]
list_shallow_copy = list_moto
list_deep_copy = list(list_moto)
print("\n中身とidを確認")
print("moto",list_moto,id(list_moto))
print("shallow",list_shallow_copy,id(list_shallow_copy))
print("deep",list_deep_copy,id(list_deep_copy))
中身とidを確認 moto [1, 2, 3] 4560848256 shallow [1, 2, 3] 4560848256 deep [1, 2, 3] 4561224384
この時点で元データとシャローコピーはid単位で同じものということが分かりますね 笑
# 内容が同じかどうかを確認 (等価判定)
print("\n等価判定")
print('shallow = moto' if list_shallow_copy == list_moto else 'shallow != moto')
print('deep = moto' if list_deep_copy == list_moto else 'deep != moto')
# identity値が同じかどうかを確認 (等値判定)
print("\n等値判定")
print('id(shallow) = id(moto)' if id(list_shallow_copy) == id(list_moto) else 'id(shallow) != id(moto)')
print('id(deep) = id(moto)' if id(list_deep_copy) == id(list_moto) else 'id(deep) != id(moto)')
# 元を変更
print("\n元を変更 list_moto[1] = 10")
list_moto[1] = 10
print("moto",list_moto)
print("shallow",list_shallow_copy)
print("deep",list_deep_copy)
# シャローコピーオブジェクトを変更
print("\nシャローコピーオブジェクトを変更 list_shallow_copy[2] = 20")
list_shallow_copy[2] = 20
print("moto",list_moto)
print("shallow",list_shallow_copy)
print("deep",list_deep_copy)
# ディープコピーオブジェクトを変更
print("\nディープコピーオブジェクトを変更 list_deep_copy[0] = 100")
list_deep_copy[0] = 100
print("moto",list_moto)
print("shallow",list_shallow_copy)
print("deep",list_deep_copy)
等価判定 shallow = moto deep = moto 等値判定 id(shallow) = id(moto) id(deep) != id(moto) 元を変更 list_moto[1] = 10 moto [1, 10, 3] shallow [1, 10, 3] deep [1, 2, 3] シャローコピーオブジェクトを変更 list_shallow_copy[2] = 20 moto [1, 10, 20] shallow [1, 10, 20] deep [1, 2, 3] ディープコピーオブジェクトを変更 list_deep_copy[0] = 100 moto [1, 10, 20] shallow [1, 10, 20] deep [100, 2, 3]
ポイントはシャローコピーも元データも要素を変更すると両方変わってしまうという点とディープコピーは完全に独立していそう(自分自身の変更しか影響しない)という点かなと思います。
作業しているうちにちょっと疑問に思ったことがあるので、下記はChatGPT先生に聞いてみた回答を自分なりに解釈して修正した内容です。
シャローコピーはいつ使うのがいいのか
シャローコピーは、オブジェクトが大きい場合にメモリ使用量を削減するために使用することができます。オブジェクトが大きい場合、ディープコピーを行うとコピーに時間がかかり、また大量のメモリを消費する可能性があります。そのため、オブジェクトの内容を変更することがない場合は、シャローコピーを使用することでメモリ使用量を削減することができます。
また、複数の変数が同じオブジェクトを参照する必要がある場合にもシャローコピーが便利です。例えば、複数の関数で同じオブジェクトを使用する場合、シャローコピーを使用することでオブジェクトを一度だけ作成して複数の変数からアクセスすることができます。
そもそもなぜオブジェクトをコピーする必要があるのか?同じ変数を使い回せばいいのではないか
プログラミングにおいて、同じ変数を使い回すことは必ずしも問題ではありませんがオブジェクトによってはコピーを作成する必要があります。
1つの理由として、オブジェクトの参照が変わる可能性があるためという理由が挙げられます。
同じ変数に異なるオブジェクトを代入する場合、その変数が参照しているオブジェクトが変わることになります。これは、参照型のオブジェクトの場合によくある問題になります。
例えばある関数で受け取ったリストを変更すると、そのリストが参照しているオブジェクトが変更される可能性があります。その後、同じ変数に別のリストを代入すると、以前のリストが参照していたオブジェクトが解放されることになり、予期しないエラーが発生する可能性があります。
他にもオブジェクトがイミュータブル(不変)である場合はコピーが必要になる場合があります。イミュータブルなオブジェクトは、変更不可能であるため、変更するためには新しいオブジェクトを作成する必要があります。Pythonの文字列やタプルはイミュータブルのため、新しいオブジェクトをコピーして作成する必要があります。
要するに、同じ変数に対して色々な情報を出し入れしているうちに参照元が変になってしまいバグになる危険性を防ぐためや、そもそもコピーしないと元の情報を保持した別のオブジェクト作れないよねということのようです。
Pythonでクラス作成 (オブジェクト指向)
今回はHumanクラスというのを作ってみます。Javaなど勉強したことがある人であればすでに見覚えがある方が多いのではないでしょうか?
ちなみに面接の準備で、objectとclassの違いは何かという問題があったことを今でも覚えています。答えはobject is an instance of class
class Human:
# 初期化 (インスタンスが生成されるたびに自動的に呼び出される)
def __init__(self, name="ヒノマルク", weight=70.0):
self._name = name
self._weight = weight
# eatメソッド
def eat(self, grams):
print(f"{grams/1000}kg食べました。") # 食べた分だけ増えます 笑
self._weight += grams/1000
# getterメソッド
def get_name(self):
return self._name
def get_weight(self):
return self._weight
# setterメソッド
def set_name(self, name):
self._name = name
def set_weight(self, weight):
self._weight = weight
# クラスのインスタンス化とメソッドの呼び出し
h = Human()
print(f"{h.get_weight()}kgです。")
h.eat(100)
print(f"{h.get_weight()}kgです。")
70.0kgです。 0.1kg食べました。 70.1kgです。
(補足) なぜselfが必要なのか
eatメソッドなどの引数にselfが必要な理由は、インスタンスメソッドであるためです。インスタンスメソッドとは、クラスに定義されたメソッドのうち、インスタンスに対して呼び出されるメソッドのことです。
selfは、インスタンスメソッド内でインスタンス自身を参照するためのキーワードです。selfを使うことで、インスタンス変数や他のインスタンスメソッドを呼び出すことができます。例えば、self._weightは、インスタンス変数 _weight にアクセスするために使われます。
通常、クラス内のすべてのインスタンスメソッドには、selfパラメータが必要です。selfは、インスタンス自身を参照するためのキーワードであり、メソッドがどのインスタンスに属するかを識別するために必要です。
(補足) なぜ変数の前にアンダーバーがついているのか
Pythonでは、変数名の先頭にアンダースコアを付けることで、その変数がプライベートであることを示すことができます。ただし、Pythonでは厳密なアクセス制御ができないため、アンダースコアを付けても完全に隠すことはできません。Humanクラスの場合、インスタンス変数_nameと_weightにアンダースコアを付けることで、その変数がプライベートであることを示すことができます。クラス外からもアクセス可能であることに注意する必要がありますが、プライベート変数であることを示すためにアンダースコアを使うことが、Pythonの一般的な慣習となっています。
Pythonのコマンドライン引数を確認してみる
よくpython3 aaa.py -f input.txtなどと引数を指定するのを見ますが、どうやるのか確認してみました。
argparseを使えば可能のようで、サンプルプログラムを作りました。
import argparse
parser = argparse.ArgumentParser(description='ファイルを読み込みます')
parser.add_argument('-f', '--file', type=str, help='インプットファイル名', required=True)
parser.add_argument('-n', '--number', type=int, help='整数を指定してください', required=False)
parser.add_argument('-o', '--output', type=str, help='出力先ファイル名', default='result.txt')
args = parser.parse_args()
print('インプットファイル名:', args.file)
print('入力された整数:', args.number)
print('出力先ファイル名:', args.output)
python3.8 arg_test.py -f input.txt -n 10 -o output.txt
インプットファイル名: input.txt 入力された整数: 10 出力先ファイル名: output.txt
python3.8 arg_test.py --help
usage: arg_test.py [-h] -f FILE [-n NUMBER] [-o OUTPUT] ファイルを読み込みます optional arguments: -h, --help show this help message and exit -f FILE, --file FILE インプットファイル名 -n NUMBER, --number NUMBER 整数を指定してください -o OUTPUT, --output OUTPUT 出力先ファイル名
よく見たことがあるアウトプットですね。
まとめ
長くなってしまいましたが、Pythonを扱う上で必要な知識を色々まとめることが出来たと思います。
自分としては色々なところを参照せずに本記事を見るだけで業務を円滑に進めることが出来たらなと思っています。