こんな人にオススメ
pythonの初歩的なlist
とかif
とかってどうやって書くの?
ひとまとめで一覧できるようにしたい!
ということで、今回は超ロング記事なpythonの初歩的な内容まとめ。list
やif
、for
など初歩的な内容の簡単な部分だけを書いているので、python初めたての方も理解しやすいのではないだろうか。
また、挙動に疑問がある場合も本記事で確認可能。辞書的な感じでお使いいただければ幸いだ。なお、処理の一部はpythonのバージョンによっては使えない場合がある。その場合は代替コードに変更していただきたい。
(目次が長いのは節表示をしているためと、本サイトの設定などが目次の折りたたみに対応していないから。ご理解いただけると幸いです。)
python環境は以下。
- Python 3.9.4
- numpy 1.20.3
list
(リスト)
list
(リスト)とは変数をひとまとめにした箱のようなもの。3個くらいなら一つ一つに変数名を割り当ててもいいが、これが1000などになると変数名の割り当てや記述、管理が大変になる。
ということでそれらをまとめてlist
にして一括管理しようというわけだ。過去にも記事を出しているのでそちらも参考にしていただければと思う。
-
-
【python&list】pythonのlistの超基礎
続きを見る
list
の作り方
list
は[]
でくくるかlist()
にする。
# listの作り方 lst = [0, 1, 2] print(lst) # [0, 1, 2] print(type(lst)) # <class 'list'> lst = list((0, 1, 2)) print(lst) # [0, 1, 2] print(type(lst)) # <class 'list'>
range
関数を使えば連続的に作成可能。
lst = list(range(10)) print(lst) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list
× 数値
list
に数値をかけるとlist
が複製される。
# 数値の掛け算 lst = [0, 1, 2] print(lst * 2) # [0, 1, 2, 0, 1, 2] print(type(lst)) # <class 'list'>
要素を数値倍したいなら以下のmap
関数や、後述のfor
などを使用する必要がある。
lst_2 = list(map(lambda x: x * 2, lst)) print(lst_2) # [0, 2, 4]
また、numpy
なら数値倍が可能。型がlist
ではなくなるのでlist
にする必要がある。
import numpy as np # numpyなら倍数にできる lst = [0, 1, 2] arr = np.array(lst) print(type(arr)) # <class 'numpy.ndarray'> print(arr * 2) # [0 2 4] print((arr * 2).tolist()) # [0, 2, 4] print(type((arr * 2).tolist())) # <class 'list'>
list
同士の掛け算
list
同士の掛け算はできない。
# list同士の掛け算 lst1 = [0, 1, 2] # lst2 = [10, 20, 30] # print(lst1 * lst2) # # print(lst1 * lst2) # # TypeError: can't multiply sequence by non-int of type 'list'
numpy.ndarray
なら同じ要素数か要素数1
なら掛け算可能。
arr1 = np.array([0, 1, 2]) arr2 = np.array([10, 20, 30]) print(arr1 * arr2) # [ 0 20 60] arr3 = np.array([100]) print(arr1 * arr3) # [ 0 100 200] arr4 = np.array([100, 1000]) # print(arr1 * arr4) # print(arr1 * arr4) # ValueError: operands could not be broadcast together with shapes (3,) (2,)
要素の追加
.append
で要素を追加。
# 要素を追加 lst = [0, 1, 2] lst.append(10) print(lst) # [0, 1, 2, 10] # 配列はそのまま入る lst = [0, 1, 2] lst.append([10, 20]) print(lst) # [0, 1, 2, [10, 20]]
list
を展開して入れようとするとエラー。list
を入れたいなら.extend
を使用する。
# append内には1つしかおけない=アンパックするとエラー lst = [0, 1, 2] # lst.append(*[10, 20]) # print(lst) # # lst.append(*[10, 20]) # # TypeError: list.append() takes exactly one argument (2 given) lst = [0, 1, 2] lst.extend([10, 20]) print(lst) # [0, 1, 2, 10, 20]
もしくはシンプルに足し算。
lst1 = [0, 1, 2] lst2 = [10, 20, 30] lst = lst1 + lst2 print(lst) # [0, 1, 2, 10, 20, 30]
スライス
スライスは簡単に言えば配列(list
とか)から規則にしたがって要素を取り出すこと。例えば1
番目から8
番目までの要素を2
つごとに抽出とか。[]
を使用して抽出。
# スライス lst = [0, 1, 2] lst01 = lst[:2] print(lst01) # [0, 1] lst01 = lst[0:2] print(lst01) # [0, 1] lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lst345 = lst[3:6] print(lst345) # [3, 4, 5] # 負符号は最後から勘定 lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lstm1 = lst[-1] print(lstm1) # 9 lstfm4 = lst[-4:] print(lstfm4) # [6, 7, 8, 9] lstfm52 = lst[-5:-2] print(lstfm52) # [5, 6, 7] # 何要素飛ばしか指定可能 lststp2 = lst[::2] print(lststp2) # [0, 2, 4, 6, 8] lst36stp2 = lst[3:6:2] print(lst36stp2) # [3, 5]
要素の検索
要素の検索には.index
を使用。
# 要素検索 lst = [0, '1', 'two', 3.0] print(lst) # [0, '1', 'two', 3.0] lst_indx0 = lst.index(0) print(lst_indx0) # 0 lst_indx1 = lst.index('1') print(lst_indx1) # 1 lst_indxtw0 = lst.index('two') print(lst_indxtw0) # 2 lst_indxtw3 = lst.index(3.0) print(lst_indxtw3) # 3
整数と小数の区別はされない。
# 小数、整数は区別されない lst_indxtw3 = lst.index(3) print(lst_indxtw3) # 3 # 小数、整数は区別されないので初めの1がhit lst = [1, 2, 1.0, 4] print(lst.index(1.0)) # 0
存在しない要素を選ぶとエラー。
# 存在しないものはエラー # lst_indxtw3 = lst.index('3') # print(lst_indxtw3) # # lst_indxtw3 = lst.index('3') # # ValueError: '3' is not in list
要素の削除
del
とスライスで要素を削除することができる。スライスを指定しないと変数ごと削除。
lst = [0, 1, 2] del lst[0] print(lst) # [1, 2] lst = [0, 1, 2] del lst[0:2] print(lst) # [2] lst = [0, 1, 2] del lst[:] print(lst) # []
スライスで範囲([0:1]
とか)を使用すると= []
で削除もできる。
lst = [0, 1, 2] lst[0:1] = [] print(lst) # [1, 2]
.remove()
で要素名指定で削除。
lst = [0, 1, 2] lst.remove(2) print(lst) # [0, 1]
tuple
(タプル)
tuple
(タプル)はlist
と同じように配列の一種であるが、list
とは異なり、()
で記述し処理速度は若干早い。しかし、その分要素の変更などができないなどのデメリットがある。
tuple
の作り方
tuple
は(,)
で作成するかtuple()
で作成。
# tupleの作成 tpl = (1, 2, 3) print(tpl) # (1, 2, 3) print(type(tpl)) # <class 'tuple'> tpl = tuple((1, 2, 3)) print(tpl) # (1, 2, 3) print(type(tpl)) # <class 'tuple'>
tuple
には,
が必要。,
なしで()
とするとそれは数値とかになる。
# tupleには,が必要 ng_tpl = (1) print(ng_tpl) # 1 print(type(ng_tpl)) # <class 'int'> ok_tpl = (1,) print(ok_tpl) # (1,) print(type(ok_tpl)) # <class 'tuple'>
要素の追加
基本的tupleの要素の追加ができない。しかし、掛け算で複製はできる。
# 要素追加 tpl = (1, 2, 3) * 2 print(tpl) # (1, 2, 3, 1, 2, 3)
追加はできない。
# tupleは変更不可なのでappendがない tpl = (1, 2, 3) # tpl.append(10) # tpl.append(10) # AttributeError: 'tuple' object has no attribute 'append'
tuple
同士の足し算は可能。
# tuple同士の足し算は可能 tpl1 = (0, 1, 2) tpl2 = (10, 20, 30) tpl = tpl1 + tpl2 print(tpl) # (0, 1, 2, 10, 20, 30)
スライス
tuple
もスライスによる要素抽出が可能。
# スライス tpl = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) tpl0 = tpl[0] print(tpl0) # 0 tpl05 = tpl[0:5] print(tpl05) # (0, 1, 2, 3, 4)
要素の削除
追加同様、削除もできない。
# 要素削除 tpl = (0, 1, 2) # del tpl[0] # del tpl[0] # TypeError: 'tuple' object doesn't support item deletion
2次元配列
上記の1次元配列では列の情報だけだったが、2次元配列では行の情報が追加される。
list
の2次元配列
list
のカッコを2にすると2次元配列。
# listの中にlistを書けば2次元配列になる(tupleも同様) lst = [[1, 2, 3], [10, 20, 30]] print(lst) # [[1, 2, 3], [10, 20, 30]] print(type(lst)) # <class 'list'> print(len(lst)) # 2
配列の要素はスライスで抽出可能。1つ目のスライスで行を2つ目のスライスで列を抽出可能。
print(lst[0]) # [1, 2, 3] print(lst[0][2]) # 3 print(lst[0:2]) # [[1, 2, 3], [10, 20, 30]] print(lst[0:2][1][2]) # 30
1次元の時と同様、数値を掛け算すると複製可能。
# 掛け算をすると複製 print(lst * 2) # [[1, 2, 3], [10, 20, 30], [1, 2, 3], [10, 20, 30]]
numpy.ndarray
の2次元配列
numpy
を使用することでより高速かつ使いやすい配列を作成することができる。
import numpy as np # numpyのnumpy.ndarrayが一般的 arr = np.array(lst) # 見た目はリストだがちゃんとnumpy.ndarray print(arr) # [[ 1 2 3] # [10 20 30]] print(type(arr)) # <class 'numpy.ndarray'>
スライスはlist
の時と同じ。
# 扱い方は2次元listと同じ print(arr[0]) # [1 2 3] print(type(arr[0])) # <class 'numpy.ndarray'>
ただし、数値の掛け算は要素の数値の掛け算になる。
# numpy.ndarrayの場合は掛け算すると倍数に print(arr * 2) # [[ 2 4 6] # [20 40 60]]
dict
(辞書)
list
やtuple
などは要素だけを記すことができる。一方で、dict
ではkeys
をvalues
と結びつけることで対応関係を持つ配列を作成することができる。
dict
の作り方
dict
はkey
とvalue
を結びつける必要があるので、必ず2種類セットで書く。
# dictの作り方 dct = {'a': 1, 'b': 2, 'c': 3} print(dct) # {'a': 1, 'b': 2, 'c': 3} print(type(dct)) # <class 'dict'> dct = dict(a=1, b=2, c=3) print(dct) # {'a': 1, 'b': 2, 'c': 3} print(type(dct)) # <class 'dict'>
ただし、dict()
を使用して作成する際に、keys
に数値を選ぶとエラー。
# {}を使用した時はkeyに数値を使用可能 dct = {'a': 1, 'b': 2, 10: 3} print(dct) # {'a': 1, 'b': 2, 10: 3} # dict()の時にkeyが数値はエラー # dct = dict(a=1, b=2, 10=3) # dct = dict(a=1, b=2, 10=3) # ^ # SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
dict
のkeys
として使える型
keys
には内容が変更されないものを指定しないといけない。
# dictのkeyとして使える型 import datetime dct = { 100: 0, 'A': 1, 'B': 2, '': 3, None: 4, (1, 2, 3): 5, datetime.date(2016, 1, 1): 6, True: 7, False: 8, range(3): 10, range(0, 3): 11, range(0, 3, 1): 12, range: 13, type(list): 14, list: 15 } print(dct) # {100: 0, 'A': 1, 'B': 2, '': 3, None: 4, (1, 2, 3): 5, datetime.date(2016, 1, 1): 6, True: 7, False: 8, range(0, 3): 12, <class 'range'>: 13, <class 'type'>: 14, <class 'list'>: 15}
list
やdict
、set
は中身を変更できるのでkey
に設定できない。
# listなど、変更可能なものはkeysには設定できない # dct = {list((1, 2, 3)): 10} # dct = {list((1, 2, 3)): 10} # TypeError: unhashable type: 'list' # dct = {{1, 2, 3}: 30} # dct = {{1, 2, 3}: 30} # TypeError: unhashable type: 'set' # dct = {{'a': 10}: 40} # dct = {{'a': 10}: 40} # TypeError: unhashable type: 'dict'
keys
の取り出し
keys
の取り出しはkeys
を指定すると可能。
# 値の取り出しはkeyの名前で指定 print(dct[100]) # 0 print(dct['A']) # 1 print(dct[False]) # 8 print(dct[range(3)]) # 12 print(dct[type]) # 14 print(dct[list]) # 15
keys
の一覧は.keys()
で行う。
# key一覧は.keys()で指定 keys = dct.keys() print(keys) # dict_keys([100, 'A', 'B', '', None, (1, 2, 3), datetime.date(2016, 1, 1), True, False, range(0, 3), <class 'range'>, <class 'type'>]) print(type(keys)) # <class 'dict_keys'>
ただし、keys
のままではスライスが使えないので、list
に変換。
# .keysのままではスライスが使えない # print(keys[0]) # print(keys[0]) # TypeError: 'dict_keys' object is not subscriptable # listにすればスライスできる print(list(keys)) # [100, 'A', 'B', '', None, (1, 2, 3), datetime.date(2016, 1, 1), True, False, range(0, 3), <class 'range'>, <class 'type'>] print(list(keys)[-1]) # <class 'type'> print(type(list(keys)[-1])) # <class 'type'>
values
の取り出し
values
の一覧は.values()
で行う。
# value一覧は.values()で指定 values = dct.values() print(values) # dict_values([0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15]) print(type(values)) # <class 'dict_values'>
このままだとスライスできないので、list
に変換。
# keyと同じくvaluesだけではスライスできない # print(values[0]) # print(values[0]) # TypeError: 'dict_values' object is not subscriptable # listにすればスライスできる print(list(values)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15] print(list(values)[2:6]) # [2, 3, 4, 5]
keys
, values
を同時に取り出し(items
)
keys
とvalues
を同時に抽出したい時は.items()
で行う。
# keyもvalueもどちらも欲しいならitems() items = dct.items() print(items) # dict_items([(100, 0), ('A', 1), ('B', 2), ('', 3), (None, 4), ((1, 2, 3), 5), (datetime.date(2016, 1, 1), 6), (True, 7), (False, 8), (range(0, 3), 12), (<class 'range'>, 13), (<class 'type'>, 14), (<class 'list'>, 15)]) print(type(items)) # <class 'dict_items'>
スライスもlist
にすればいい。
print(list(items)) # [(100, 0), ('A', 1), ('B', 2), ('', 3), (None, 4), ((1, 2, 3), 5), (datetime.date(2016, 1, 1), 6), (True, 7), (False, 8), (range(0, 3), 12), (<class 'range'>, 13), (<class 'type'>, 14), (<class 'list'>, 15)] print(list(items)[-4]) # (range(0, 3), 12) print(type(list(items)[-4])) # <class 'tuple'> print(list(items)[-4][0]) # range(0, 3)
要素の追加
要素の追加はkeys
とvalues
を同時に指定しないともちろんいけない。dict[keys] = values
か
setdefault()
を使用する場合は
# 要素の追加 dct = {100: 0, 'A': 1, } # 要素はkeyとvaluesで追加 dct['new'] = 'NEW' print(dct) # {100: 0, 'A': 1, 'new': 'NEW'} dct.setdefault('new2', 'NEW2') print(dct) # {100: 0, 'A': 1, 'new': 'NEW', 'new2': 'NEW2'} # [key]で追加する場合はvalueは上書き dct['new'] = 'NEW_2' print(dct) # {100: 0, 'A': 1, 'new': 'NEW_2', 'new2': 'NEW2'} # setdefaultで追加する場合はvalueは上書きされない dct.setdefault('new2', 'NEW2_2') print(dct) # {100: 0, 'A': 1, 'new': 'NEW_2', 'new2': 'NEW2'}
dict
の結合(マージ)
dict
同士の結合は複数種のdict
を新たなdict
内でアンパック(展開)することで可能。ただし、dict()
形式だとkeys
が被るとエラー。
マージについては以下の記事も参照。
-
-
【辞書の結合】dictのマージ
続きを見る
# dict同士の結合(マージ) dct1 = {'A': 1, 'B': 2, '': 3, } dct2 = {'D': 10, 'E': 20, '': 30, } # 結合はアンパックで可能 # {}の時はkeyが被ると上書き print({**dct1, **dct2}) # {'A': 1, 'B': 2, '': 30, 'D': 10, 'E': 20} # dict()の時はkeyが被るとエラー # print(dict(**dct1, **dct2)) # print(dict(**dct1, **dct2)) # TypeError: dict() got multiple values for keyword argument ''
python3.9からは「|
」を用いたマージが可能に。
# python3.9からは「|」が使用可能に print(dct1 | dct2) # {'A': 1, 'B': 2, '': 30, 'D': 10, 'E': 20}
if
(条件分岐)
条件によって内容を変えたい時、例えば偶数ならある処理を、奇数なら別の処理をするときには条件分岐という考え方を使用する。pythonの条件分岐にはif
が用いられる。
True
とFalse
の判定とは(==
や>=
とか)
まずは条件分岐に必要な条件判定とは何かというものから。これは単純に、その条件に当てはまるかどうかを判定するということ。判定に使用するTrue
, False
はbool
型と呼ばれる型。
- 当てはまる = 真:
True
- 当てはまらない = 偽:
False
# TrueとFalse a = 1 b = 2 print(a < b) # bはaより大きい # True print(a > b) # bはaより小さい # False print(a <= b) # bはa以上 # True print(a >= b) # aはb以上 # False print(a == b) # aとbは等しい # False print(a != b) # aはbと等しくない # True
if
とelif
とelse
条件判定は、初めはif
で行う。それに当てはまらない条件はelse
で条件を分岐させるが、3種類以上に分岐させたいときはif
とelse
の間にelif
を入れて条件を追加する。
# ifで条件判定をし、当てはまらない場合は全てelseへ a = 1 b = 2 if a < b: print('bの方が大きい') else: print('aの方が大きい') # bの方が大きい # elifで次の条件を追加可能 a = 1 b = 1 if a < b: print('bの方が大きい') elif a == b: print('aとbは等しい') else: print('aの方が大きい') # aとbは等しい # ifでもelifに当てはまらない場合はelse a = 2 b = 1 if a < b: print('bの方が大きい') elif a == b: print('aとbは等しい') else: print('aの方が大きい') # aの方が大きい
if
だけでの条件分岐も可能。この場合はif
に当てはまらないと何も処理しない。
# ifだけでも使える(以下の場合は条件に当てはまらないので出力なし) a = 2 b = 1 if a < b: print('bの方が大きい')
配列に要素があるかどうかで条件判定(in
)
条件文は何も大小関係だけではない。ありとあらゆる条件を使用することができる。ここでは配列中にある要素が存在しているか否かで条件判定をする。存在しない場合を判定する場合を判定するにはnot
を使用する。
# 条件文は入れられる lst = [1, 2, 3] a = 1 b = 2 c = 4 if a in lst: print(f"{a}あり") # 1あり if c not in lst: print(f"{c}なし") # 4なし
複数条件を設定する
単一の条件で判断するのではなく、複数の条件を適用することも可能。その時は以下で指定可能。
- または:
条件 or 条件
、もしくは、(条件) | (条件)
- かつ:
条件 and 条件
、もしくは、(条件) & (条件)
# 複数条件もあり if a in lst or c in lst: print(f"{a}ありまたは{c}なし") # 1ありまたは4なし if (a in lst) | (c in lst): print(f"{a}ありまたは{c}なし") # 1ありまたは4なし if a in lst and b in lst: print(f"{a}ありかつ{b}なし") # 1ありかつ2なし if (a in lst) & (b in lst): print(f"{a}ありかつ{b}なし") # 1ありかつ2なし
None
, NaN
, bool
の判定(is
やnp.isnan
)
None
(何もない)、NaN
(Not a Number、非数値、データがなかったとか)、bool
(真か偽、True
とFalse
)を条件文で判定する際には注意点がある。
# NoneとNaNは判定が特殊 import numpy as np a = None b = np.nan c = True print(a, type(a)) # None <class 'NoneType'> print(b, type(b)) # nan <class 'float'> print(c, type(c)) # True <class 'bool'>
None
の判定は==
を使用しても可能だが、この場合はflake8というコードチェックに引っかかる。エラーではないが推奨されない書き方。エディタにコードチェック用のツールを導入している場合は、エディタ上で警告的なものが出る。
==
ではなくis
を使用するべし。
flake8とこれに関連するPEP8については以下の記事参照。
-
-
【PEP8&flake8】pythonにおけるPEP8とflake8
続きを見る
# None==でもエラーは出ないが、flake8の警告が出る(エディタ上で) if a == None: print('aはNone') # comparison to None should be 'if cond is None:'flake8(E711) # aはNone # is(同一性)で比較 if a is None: print('aはNone') # aはNone
bool
についても同様。なお、bool
については直で書いても既にbool
なので条件判定に使用することができる。
# boolについてもエディタ上で警告が出る if c == True: print('cはTrue') # comparison to True should be 'if cond is True:' or 'if cond:'flake8(E712) # cはTrue if c is True: print('cはTrue') # cはTrue # boolについては直で書いていい if c: print('cはTrue') # cはTrue
NaN
が一番特殊でこちらは==
がそもそも効かない。is
なら大丈夫だが、一番有名なのはnumpy
のnp.isnan()
。これはnan
であるかどうかを判定してくれるもの。
import numpy as np # NaNは==は効かない(この場合は出力なし) if b == np.nan: print('bはNaN') # isならいける if b is np.nan: print('bはNaN') # bはNaN # もしくはnp.isnan if np.isnan(b): print('bはNaN') # bはNaN
NaN
は四則演算すると結果がNaN
になったり、plt
でグラフが表示されなかったりと面倒なことが多いので使用には注意が必要。
for
(繰り返し、反復)
データを1行ずつ読み込みたいなど、何か同じ操作を繰り返し行いたい場合はfor
(繰り返し、反復)を使用する。pythonのfor
は他の言語に比べて処理が遅いので処理内容を工夫して処理が多くならないようにするのが賢明。
1重ループ
単純なループは以下。print
すると1処理ごとに改行されていることがわかる。
# range(5)で0から5までを1刻みでデータ作成 for i in range(5): print(i) # 0 # 1 # 2 # 3 # 4 # 上の例と同じ出力 # forの後の「j」は好きに変更可能(forとかrangeとかの予約後以外なら) for j in range(0, 5, 1): print(j) # 0 # 1 # 2 # 3 # 4
多重ループ
多重ループはネスト(インデントつけ)して記入する。pythonはこのインデントが厳しいのでインデントがいくつ入っているのかはしっかりと確認する必要がある。
また、多重ループでは先に書いたfor
(以下ではi
)が先に固定され、その固定の状態で後に書いたfor
(以下ではj
)のループが処理される。
# 多重ループでは先に書いた方を先に固定 for i in range(3): for j in range(10, 14): print(f"i={i}, j={j}") print('---') # i=0, j=10 # i=0, j=11 # i=0, j=12 # i=0, j=13 # --- # i=1, j=10 # i=1, j=11 # i=1, j=12 # i=1, j=13 # --- # i=2, j=10 # i=2, j=11 # i=2, j=12 # i=2, j=13 # ---
配列をそのまま取り出し(list
やdict
)
上記ではrange
関数を使用してfor
を作成したが、list
などの配列をそのままfor
に入れて処理することが可能。list
やtuple
の場合は要素が、dict
の場合はkeys
が出力される。
# listなどをそのまま入れることも可能 lst = [10, 100, 1000] for i in lst: print(i) # 10 # 100 # 1000 # dictの場合はkeysが出力 dct = {'A': 1, 'B': 2, '': 3, 'C': 4} for k in dct: print(k) # A # B # C
dict
のvalues
が欲しい時は.values()
にする。
# dictのvaluesが欲しい時は.values()にする dct = {'A': 1, 'B': 2, '': 3, 'C': 4} for v in dct.values(): print(v) # 1 # 2 # 3 # 4
keys
の場合も同様に、.keys()
と明示してもいい。
# keyが欲しい時に.keys()と明示してもいい dct = {'A': 1, 'B': 2, '': 3, 'C': 4} for k in dct.keys(): print(k) # A # B # # C
.keys()
、.values()
と()
をつけてしまうとエラー。
# .valuesとカッコなしだとエラー # for v in dct.values: # print(v) # for v in dct.values: # TypeError: 'builtin_function_or_method' object is not iterable # .keysも同様 # for k in dct.keys: # print(k) # for k in dct.keys: # TypeError: 'builtin_function_or_method' object is not iterable
dict
のkeys
もvalues
も欲しい時は.items()
。keys
とvalues
の2つの値があるのでfor
の引数を2つにすると別々に取り出せる。
# keysもvaluesも欲しい時は.items() for k, v in dct.items(): print(f"key: {k}, value: {v}") # key: A, value: 1 # key: B, value: 2 # key: , value: 3 # key: C, value: 4
引数を1つにするとtuple
で取り出すことができる。
# forのループ変数を一つにするとtupleで出力 for kv in dct.items(): print(f"key & value: {kv}, type(kv): {type(kv)}") # key & value: ('A', 1), type(kv): <class 'tuple'> # key & value: ('B', 2), type(kv): <class 'tuple'> # key & value: ('', 3), type(kv): <class 'tuple'> # key & value: ('C', 4), type(kv): <class 'tuple'>
複数の配列を同時for
ループ(zip
)
複数の配列を同時にfor
ループする場合はzip
関数が便利。for
の引数は1つでもいいが、この時はtuple
でまとめられる。
# 複数個の配列をループさせるならzip lst1 = [0, 1, 2] lst2 = [10, 20, 30] for l1, l2 in zip(lst1, lst2): print(f"{l1}, {l2}") # 0, 10 # 1, 20 # 2, 30
dict
のitems
を同時に取得したい場合は、それぞれのdict
ごとにカッコ()
で分ける必要がある。
# 2つのdictのitemsを同時に取得したい時はそれぞれをカッコでくくる dct1 = {'A': 1, 'B': 2, 'C': 3, } dct2 = {'D': 10, 'E': 20, 'F': 30, } for (k1, v1), (k2, v2) in zip(dct1.items(), dct2.items()): print(f"dct1: {k1} & {v1}, dtc2: {k2} & {v2}") # dct1: A & 1, dtc2: D & 10 # dct1: B & 2, dtc2: E & 20 # dct1: C & 3, dtc2: F & 30
インデックスも同時取得(enumerate
)
for
ループで得られるデータが何番目のデータなのかなど、インデックスも同時に取得したい時はenumerate
が便利。for
のすぐ後にenumerate
の引数を書く。また、enumerate
の勘定始まりの数は0
だが好きな値に変更可能。
# ループのインデックスを取得したいならenumerate lst = [10, 100, 1000] for num, i in enumerate(lst): print(f"No.{num}: {i}") # No.0: 10 # No.1: 100 # No.2: 1000 # 好きな番号から始めるときは引数追加 lst = [10, 100, 1000] for num, i in enumerate(lst, -1): print(f"No.{num}: {i}") # No.-1: 10 # No.0: 100 # No.1: 1000
enumerate
にはステップ数を指定する引数はない。したがって3
ずつ記述など、1
ではない場合は処理中に書く必要がある。
# ステップ数を表す引数はない lst = [10, 100, 1000] # for num, i in enumerate(lst, 1, 3): # print(f"No.{num}: {i}") # for num, i in enumerate(lst, 1, 3): # TypeError: enumerate() takes at most 2 arguments (3 given) # 出力時に調整すればOK for num, i in enumerate(lst, 1): print(f"No.{num * 3}: {i}") # No.3: 10 # No.6: 100 # No.9: 1000
zip
とenumerate
を同時に回す
zip
で複数のデータを回しつつenumerate
でそのインデックスも取得したい場合は、enumerate
とzip
の引数をカッコ()
で分ける必要がある。
# enumerateとzipを併用する際には、zip部分をカッコでくくる lst1 = [0, 1, 2] lst2 = [10, 20, 30] for num, (l1, l2) in enumerate(zip(lst1, lst2), 1): print(f"No.{num}: {l1}, {l2}") # No.1: 0, 10 # No.2: 1, 20 # No.3: 2, 30
カッコしないとエラー。
# zip部分は別途カッコで括らないとエラー # lst1 = [0, 1, 2] # lst2 = [10, 20, 30] # for num, l1, l2 in enumerate(zip(lst1, lst2), 1): # print(f"No.{num}: {l1}, {l2}") # for num, l1, l2 in enumerate(zip(lst1, lst2), 1): # ValueError: not enough values to unpack (expected 3, got 2)
複数のdict
のkeys
とvalues
を取得しつつインデックスも取得したい場合は、enumerate
とzip
を分けるカッコに加えてそれぞれのzip
を分けるカッコも必要。
# 2つのdictのitemsを取得しつつ、インデックスも欲しい時は区別するカッコも必要 dct1 = {'A': 1, 'B': 2, 'C': 3, } dct2 = {'D': 10, 'E': 20, 'F': 30, } for num, ((k1, v1), (k2, v2)) in enumerate(zip(dct1.items(), dct2.items()), 1): print(f"No.{num}...dct1: {k1} & {v1}, dtc2: {k2} & {v2}") # No.1...dct1: A & 1, dtc2: D & 10 # No.2...dct1: B & 2, dtc2: E & 20 # No.3...dct1: C & 3, dtc2: F & 30
for
の中にif
を入れる
for
の中にif
を入れて、反復処理をしながら条件分岐も可能。
# forにifを入れる for i in range(10): if i < 7: if i % 2 == 0: # 余りを計算 print(f"{i}は7未満であり偶数") else: print(f"{i}は7未満であり奇数") else: print(f"{i}は7以上") # 0は7未満であり偶数 # 1は7未満であり奇数 # 2は7未満であり偶数 # 3は7未満であり奇数 # 4は7未満であり偶数 # 5は7未満であり奇数 # 6は7未満であり偶数 # 7は7以上 # 8は7以上 # 9は7以上
内包表記(短縮版for
)
内包表記を使用すれば、for
文を1行で書くことができる。処理が通常のfor文よりも速くなるものの、見づらかったりするので多用はいけない。他の部分で処理を早くするべし。
シンプルな内包表記
通常のforだと5行分のコードが、内包表記だと3行で済む。
# 内包表記 lst = [i for i in range(2, 5)] print(lst) # [2, 3, 4] # 上記は以下と同等 lst = [] for i in range(2, 5): lst.append(i) print(lst) # [2, 3, 4]
多重ループの内包表記
多重ループの時は、内包表記内でカッコ[]
を使用するか否かで処理が異なる。
まずは内包表記内にカッコがない場合。この場合は左側のfor
を先に固定し、右側のfor
を回す。
# 同時ループでは左側を固定して右側を回す lst = [f"{i}{j}" for i in ('A', 'B', 'C') for j in [1, 2, 3]] print(lst) # ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'] # 上記は以下と同等 lst = [] for i in ('A', 'B', 'C'): for j in [1, 2, 3]: lst.append(f"{i}{j}") print(lst) # ['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
一方で内包表記内にカッコがあると多次元配列として扱うことになる。この場合は右側のfor
を先に固定し、左側のfor
を回すことになる。
# 左側のループをさらに[]でくくると、右側を先に固定 lst = [[f"{i}{j}" for i in ('A', 'B', 'C')] for j in [1, 2, 3]] print(lst) # [['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ['A3', 'B3', 'C3']] # 上記は以下と同等 lst = [] for j in [1, 2, 3]: lst_in = [] for i in ('A', 'B', 'C'): lst_in.append(f"{i}{j}") lst.append(lst_in) print(lst) # [['A1', 'B1', 'C1'], ['A2', 'B2', 'C2'], ['A3', 'B3', 'C3']]
内包表記とif
内包表記内にif
を使用することもできる。if
だけの場合は最後に書く。
# 内包表記でもifは使用可能 lst = [i for i in range(10) if i % 2 == 0] print(lst) # [0, 2, 4, 6, 8] # 上記は以下と同等 lst = [] for i in range(10): if i % 2 == 0: lst.append(i) print(lst) # [0, 2, 4, 6, 8]
else
が入る場合はif
とelse
を初めに書く。
# elseを入れたいときは先に書く(以下は偶数ならe、奇数ならoを初めにつける) lst = [f"e{i}" if i % 2 == 0 else f"o{i}" for i in range(10)] print(lst) # ['e0', 'o1', 'e2', 'o3', 'e4', 'o5', 'e6', 'o7', 'e8', 'o9'] # 上記は以下と同等 lst = [] for i in range(10): if i % 2 == 0: ans = f"e{i}" else: ans = f"o{i}" lst.append(ans) print(lst) # ['e0', 'o1', 'e2', 'o3', 'e4', 'o5', 'e6', 'o7', 'e8', 'o9']
elif
は使用できないので、3種類以上の条件を入れたい場合はelse
の後に再度if
を書く必要がある。以下の例だと、偶数にはe
をつけ、3の倍数は最後に!
を、そしてそれ以外にはother
とつけている。
ただし、内包表記で書くとPEP8の79文字制限に違反しており、さらに内容も複雑になり可読性が低いの多用はしないほうがいいだろう。
PEP8については以下参照。
-
-
【PEP8&flake8】pythonにおけるPEP8とflake8
続きを見る
lst = [f"e{i}" if i % 2 == 0 else f"{i}!" if i % 3 == 0 else f"other{i}" for i in range(10)] print(lst) # ['e0', 'other1', 'e2', '3!', 'e4', 'other5', 'e6', 'other7', 'e8', '9!'] # 上記は以下と同等 lst = [] for i in range(10): if i % 2 == 0: ans = f"e{i}" elif i % 3 == 0: ans = f"{i}!" else: ans = f"other{i}" lst.append(ans) print(lst) # ['e0', 'other1', 'e2', '3!', 'e4', 'other5', 'e6', 'other7', 'e8', '9!']
関連記事
-
-
【python&独学】独学である程度pythonを習得するマインド
続きを見る
-
-
【python&list】pythonのlistの超基礎
続きを見る
-
-
【Mac&タイピング】タッチタイピングで分間300打を超える方法
続きを見る