辻 真吾(www.tsjshg.info)
Pythonを使ったデータサイエンスが得意
最近はRustを書きたい
RISC-Vに興味がある
Python、データサイエンス、アルゴリズムに関する著書多数
毎月1回オンラインで『みんなんのPython勉強会』をやっています
基本的なデータ構造のはなし
データ構造を組み合わせて使うはなし
比較のはなし
データを順番に保持するデータ型
my_list = [1, 2, 3]
# 要素の追加が可能
my_list.append(4)
my_list
[1, 2, 3, 4]
list
にしない
list
がその後使えなくなってしまうためデータを順番に保持するデータ型(変更できない)
my_tuple = (1, 2, 3)
my_tuple
(1, 2, 3)
データの対応を保持するデータ型
my_dict = {'A': 1, 'B': 2, 'C': 3}
my_dict['B']
2
順序を持たず重複のないデータの集まり
my_set = {1, 1, 2, 3, 3}
my_set
{1, 2, 3}
set
では挿入順序は保持されません変更できないset
my_fs = frozenset((1, 2, 2, 3, 3))
my_fs
frozenset({1, 2, 3})
set
とfrozenset
my_dict[['A', 'B']] = 'エビ'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[94], line 1
----> 1 my_dict[['A', 'B']] = 'エビ'
TypeError: unhashable type: 'list'
my_set.add([5, 6])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[95], line 1
----> 1 my_set.add([5, 6])
TypeError: unhashable type: 'list'
同じエラーが出ている
組込関数hash
でエラー無くハッシュ値(整数)が得らるオブジェクトは辞書のキーやset
の要素にできる
hash(my_list)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[96], line 1
----> 1 hash(my_list)
TypeError: unhashable type: 'list'
hash(my_tuple)
529344067295497451
set
の内部で利用されているhash
以外に暗号学的ハッシュ関数を揃えたhashlib
があるメニューは料理名と価格のペアをタプルで保持
# タプルのリスト
# 改行しているのはPDF資料のためで、1行で書きます
menu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
[v[0] for v in menu]
['刺身定食', 'あじフライ定食', '天ぷらうどん']
メニューの名前だけからなる新たなリストを作成
menu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
[(x[0], y[0]) for x in menu for y in menu if x != y]
[('刺身定食', 'あじフライ定食'),
('刺身定食', '天ぷらうどん'),
('あじフライ定食', '刺身定食'),
('あじフライ定食', '天ぷらうどん'),
('天ぷらうどん', '刺身定食'),
('天ぷらうどん', 'あじフライ定食')]
for
文で書く方が良いという意見が多いmenu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
{v[0]: v[1] for v in menu}
{'刺身定食': 1200, 'あじフライ定食': 1000, '天ぷらうどん': 900}
キーは料理名、値は価格になっている辞書を作成
menu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900), ("刺身定食", 1200)]
{v[0] for v in menu}
{'あじフライ定食', '刺身定食', '天ぷらうどん'}
my_list = [6, 4, 3]
sorted(my_list)
[3, 4, 6]
sorted
関数とsort
メソッドがあるsort
メソッドを使うとリスト自体を変更するmenu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
sorted([(v[1], v[0]) for v in menu])
[(900, '天ぷらうどん'), (1000, 'あじフライ定食'), (1200, '刺身定食')]
各タプルの最初の要素で昇順にソートしてくれる
menu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
sorted(menu, key=lambda v: v[1])
[('天ぷらうどん', 900), ('あじフライ定食', 1000), ('刺身定食', 1200)]
sorted
関数のkey
引数に関数を渡してどの値でソートするかを指示できるlambda
を使った無名関数はこういう場面で便利from operator import itemgetter
menu = [("刺身定食", 1200), ("あじフライ定食", 1000),
("天ぷらうどん", 900)]
sorted(menu, key=itemgetter(1))
[('天ぷらうどん', 900), ('あじフライ定食', 1000), ('刺身定食', 1200)]
import
が面倒なので、個人的にはlambda
で無名関数を渡すのが好き# 順番が保持される
my_dict = {'b': 2, 'c': 3, 'a': 1}
for k in sorted(my_dict):
print(f"{k} : {my_dict[k]}")
a : 1
b : 2
c : 3
for
で表示するとリテラルで記述した順番になるenumerate
関数にはstart
という引数がある
sakana = ['いわし', 'さんま', 'かつお', 'まぐろ']
for i,v in enumerate(sakana, start=10):
print(i, v)
10 いわし
11 さんま
12 かつお
13 まぐろ
'A' == "A"
True
書き方の違いでしかないので、当たり前
n = None
n is None
True
Noneはシングルトン(その実行環境にインスタンスが1つだけ)なので、is
とis not
を使った比較をしてくださいとPEP8(Pythonの公式コーディング規約)に書いてある
1 == 1.0 == True
True
{1, 1.0, True}
{1}
set
を作ると1つにまとまる[1, 2, 3] == [1, 2, 3]
True
[1, 3, 2] == [1, 2, 3]
False
{1, 3, 2} == {1, 2, 3, 2}
True
from collections import namedtuple
Dish = namedtuple('Dish', ['name', 'price'])
menu = [Dish('刺身定食', 1200), Dish('あじフライ定食', 1000),
Dish('天ぷらうどん', 900), Dish('とろろそば', 900)]
menu
[Dish(name='刺身定食', price=1200),
Dish(name='あじフライ定食', price=1000),
Dish(name='天ぷらうどん', price=900),
Dish(name='とろろそば', price=900)]
menu[0][0] == "刺身定食"
はTure
sorted(menu, key=lambda x: x.price)
[Dish(name='天ぷらうどん', price=900),
Dish(name='とろろそば', price=900),
Dish(name='あじフライ定食', price=1000),
Dish(name='刺身定食', price=1200)]
型ヒント付きの名前付きタプル
from typing import NamedTuple
class TypedDish(NamedTuple):
name: str
price: int
sashimi = TypedDish('刺身定食', 1200)
aji = TypedDish('あじフライ定食', '1000')
型が違ってもエラーにはならない
class TypedDish(NamedTuple):
name: str
price: int
def __eq__(self, value):
return self.price == value.price
tempura = TypedDish('天ぷらうどん', 900)
tororo = TypedDish('とろろそば', 900)
tempura == tororo
True
from dataclasses import *
@dataclass
class Dish:
name: str
price: int
tempura = Dish('天ぷらうどん', 900)
namedtuple
、NamedTuple
、dataclass
どれがいい?
dataclass
を1番に考えるのがよさそうdataclass(frozen=True)
とすれば手軽にハッシュ可能になる(thanks to たかのりさん)set
の要素になれるご清聴ありがとうございました!