Recommended
PPTX
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
PDF
「のどが渇いた」というユーザーに何を出す? ユーザーの「欲しい」に惑わされない、本当のインサイトを見つけるUXデザイン・UXリサーチ
PDF
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
PDF
Machine learning CI/CD with OSS
PDF
PDF
PlaySQLAlchemy: SQLAlchemy入門
PDF
Apache Arrow - データ処理ツールの次世代プラットフォーム
PPTX
BuildKitによる高速でセキュアなイメージビルド
PPTX
世界一わかりやすいClean Architecture
PDF
PPTX
NGINXをBFF (Backend for Frontend)として利用した話
PDF
[AWS EXpert Online for JAWS-UG 18] 見せてやるよ、Step Functions の本気ってやつをな
PDF
マイクロサービスバックエンドAPIのためのRESTとgRPC
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
PDF
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
PDF
入門 Kubeflow ~Kubernetesで機械学習をはじめるために~ (NTT Tech Conference #4 講演資料)
PPTX
PPTX
PDF
Java Clientで入門する Apache Kafka #jjug_ccc #ccc_e2
PPTX
PDF
PDF
PDF
PPTX
PPTX
PDF
Python と型ヒント (Type Hints)
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
More Related Content
PPTX
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
PDF
「のどが渇いた」というユーザーに何を出す? ユーザーの「欲しい」に惑わされない、本当のインサイトを見つけるUXデザイン・UXリサーチ
PDF
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
PDF
Machine learning CI/CD with OSS
PDF
PDF
PlaySQLAlchemy: SQLAlchemy入門
PDF
Apache Arrow - データ処理ツールの次世代プラットフォーム
PPTX
BuildKitによる高速でセキュアなイメージビルド
What's hot
PPTX
世界一わかりやすいClean Architecture
PDF
PPTX
NGINXをBFF (Backend for Frontend)として利用した話
PDF
[AWS EXpert Online for JAWS-UG 18] 見せてやるよ、Step Functions の本気ってやつをな
PDF
マイクロサービスバックエンドAPIのためのRESTとgRPC
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
PDF
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け
PDF
PDF
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
PDF
入門 Kubeflow ~Kubernetesで機械学習をはじめるために~ (NTT Tech Conference #4 講演資料)
PPTX
PPTX
PDF
Java Clientで入門する Apache Kafka #jjug_ccc #ccc_e2
PPTX
PDF
PDF
PDF
PPTX
PPTX
Similar to Python standard 2022 Spring
PDF
Python と型ヒント (Type Hints)
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
PDF
PDF
PPTX
PDF
PDF
次世代言語 Python による PyPy を使った次世代の処理系開発
PDF
KEY
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
PDF
PPT
PDF
S02 t1 sta_py_tsuji_0702_slides
PDF
「Python言語」はじめの一歩 / First step of Python / 2016 Jan 12
PDF
20170131 python3 6 PEP526
PDF
PDF
「Python言語」はじめの一歩 / First step of Python
PDF
LLdeade Python Language Update
PDF
PPTX
Python standard 2022 Spring 1. 2. 3. 4. 5. 6. 7. 8. pyproject.toml設定例 –format
black は 88桁改行なので、isort にそれを教える必要がある
[tool.poe.env]
LINT_TARGETS = "my_project tests"
[tool.poe.tasks]
fmt-black = "black $LINT_TARGETS"
fmt-docformatter = "docformatter -ri $LINT_TARGETS"
fmt-isort = "isort $LINT_TARGETS"
fmt = ["fmt-isort", "fmt-black", "fmt-docformatter"]
[tool.isort]
profile = "black"
$ poetry run poe fmt
$ poetry run poe fmt-black
9. 10. 11. pyright設定例 –lint
設定例
[tool.pyright]
venvPath = "."
venv = ".venv"
typeCheckingMode = "strict"
#reportImportCycles = "warning"
reportMissingTypeStubs = "none"
reportUnknownArgumentType = "none"
reportUnknownLambdaType = "none"
reportUnknownMemberType = "none"
reportUnknownParameterType = "none"
reportUnknownVariableType = "none"
reportUnnecessaryIsInstance = "none"
reportUntypedFunctionDecorator = "none"
12. 13. flake8–lint
昔からある Python の lint プログラム
pyright があれば不要かもしれないが念のため使うくらい
pyproject.tomlの採用を頑なに拒んでいるくらい既に香ばしい
設定例 (setup.cfg)
[flake8]
max-line-length = 88
extend-ignore = E203
14. pyproject.toml設定例 –lint
pyright,mypy,flake8,format ツールの順がおすすめ
[tool.poe.env]
LINT_TARGETS = "my_project tests"
[tool.poe.tasks]
lint-black = "black --check --diff $LINT_TARGETS"
lint-docformatter = "docformatter -rc $LINT_TARGETS"
lint-flake8 = "flake8 $LINT_TARGETS"
lint-isort = "isort --check --diff $LINT_TARGETS"
lint-mypy = "mypy $LINT_TARGETS"
lint-pyright = "pyright $LINT_TARGETS"
lint = ["lint-pyright", "lint-mypy", "lint-flake8",
"lint-docformatter", "lint-black", "lint-isort"]
$ poetry run poe lint
15. 16. 17. 18. 19. 型アノテーションの基礎(1)–typing
a: str = "Hello, World!" # OK
b: int = "Hello, World!" # NG
c = "Hello, World!" # c は str と推論される
c = 3 # NG: c は str なのでエラー
d: str | int = "Hello, World!" # OK: Python 3.10 未満では Union[str, int]
d = 3 # OK
d = [3] # NG: list[int] を代入しようとしている
e: Any = "Hello, World!" # OK
e = 3 # OK
e = [3] # OK
20. 型アノテーションの基礎(2)–typing
t1: tuple[float, float] = (0.0, 0.0) # OK
t2: tuple[str, int] = ("foo", "bar") # NG: "bar" は int ではない
l1: list[int] = [1, 2, 3] # OK
l2: list[int] = [1, 2, "string"] # NG: "string" は int ではない
l3 = [1, 2, True] # l3 は list[int | bool] と推論される
l3.append(3) # OK
l3.append([5]) # NG: list[int] は追加できない
l4: list[Any] = [1, 2, True]
l4.append([5]) # OK
d = {"a": 1, "b": 2} # d は dict[str, int]
d[(1, 2)] = 1 # NG: key の (1, 2) は str ではない
d["c"] = "string" # NG: value の "string" は int ではない
21. 型アノテーションの基礎(3)–typing
def square(x: float) -> float:
return x * x
square("3") # NG: "3" は float ではない
square(3.0) # OK
square(3) # OK!: 3 は float ではないが…
a: str = square(3) # NG: square(3) の結果は str ではない
def pow(x: float, y: float) -> float:
return "string" # NG: 戻り値が float ではない
f: Callable[[float, float], float] = pow
22. 型アノテーションの基礎(4)–typing
a: Optional[int] = 1 # OK: Optional[int] は int | None と同じ意味
a = None # OK
a = "string" # NG: int でも None でもない
def _sq_opt(x: Optional[int]) -> int:
return x * x # NG: x は None かもしれない
def sq_opt(x: Optional[int]) -> int:
if x is None:
return 0
return x * x # OK: ここでは x が None ではない保証がある
def union_test(x: str | int) -> None:
y: int = x # NG: x は str かもしれない
if isinstance(x, int):
y: int = x # OK
else: # ここが isinstance(x, str) だと pyright が警告 (reportUnnecessaryIsInstance)
y: str = x # OK
23. 24. dataclass–typing
Python のクラス定義の新標準
@dataclass
class NewClass:
version: ClassVar[str] = "1.0"
name: str
address: str
latitude: float
longitude: float
class OldClass:
version = "1.0"
def __init__(self, name: str, addrss: str, latitude: float, longitude: float) -> None:
self.name: str = name
self.address: str = name # 書き間違い!
self.latitude: float = latitude
self.longitude: float = longitude
25. dataclassの例 –typing
from __future__ import annotations # User から User の再帰的参照のため
@dataclass
class User:
version: ClassVar[str] = "1.0"
id: int
name: str
following: list[User] = field(default_factory=list)
a = User(1, "User A")
# User(id=1, name='User A', following=[])
b = User(2, "User B", [a])
# User(id=2, name='User B', following=[User(id=1, name='User A', following=[])])
a.following.append(b)
# User(id=1, name='User A', friends=[User(id=2, name='User B', friends=[...])])
26. dataclass_json–typing
dataclassの JSON シリアライザ・デシリアライザ
Rust の serde/serde_json のように使える
# 循環参照があるとシリアライズがエラーになるので例はあまり良くない
@dataclass
class User(DataClassJsonMixin):
id: int
name: str
following: list[User] = field(default_factory=list)
a = User(1, "User A")
b = User(2, "User B", [a])
# User(id=2, name='User B', following=[User(id=1, name='User A', following=[])])
b.to_dict()
# {'id': 2, 'name': 'User B', 'following': [{'id': 1, 'name': 'User A', 'following': []}]}
b.to_json()
# '{"id": 2, "name": "User B", "following": [{"id": 1, "name": "User A", "following": []}]}'
assert b == User.from_dict(b.to_dict()) # OK
assert b == User.from_json(b.to_json()) # OK
27. 28. dataclass_json応用(2)–typing
class MyEnum(Enum):
V1 = 1
V2 = 2
class EnumTest(DataClassCamelJsonMixin):
my_enum: MyEnum
x = EnumTest(MyEnum.V1)
# EnumTest(my_enum=<MyEnum.V1: 1>)
x.to_dict()
# {'myEnum': <MyEnum.V1: 1>}
x.to_dict(encode_json=True)
# {'myEnum': 1}
assert x == EnumTest.from_dict(x.to_dict(encode_json=True)) # OK
29. 30. 型検査の毒薬:Anyと dict–typing
すべての型を Anyにすれば型検査は必ず通る (ただし何の意味もない)
当然の帰結として Anyは原則禁止
例外は外部モジュールからの戻り値など、本当に型がわからない場合
dict は構造について何も示さない
dict もそれが本当に必要な場合を除いて原則禁止
必要なのは keyが予め想定できないものを格納する場合
dic: dict[str, Any] = f() # 何か API からの JSON データが入る
name = dic["name"]
# 本当に name というフィールドはあるのか?
project_id = dic["projects"][0]["id"]
# 正しいのかもしれないが、静的に構造の正しさのチェックができない。
31. 32. Anyの回避 (複数の型変数)–typing
A = TypeVar("A")
B = TypeVar("B")
def option_get(x: Optional[A], default: A) -> A:
if x is None:
return default
return x
option_get(None, 3) # -> 3
option_get(6, 3) # -> 6
option_get(6, "string") # ERROR: "string" は int ではない
def option_map(x: Optional[A], f: Callable[[A], B]) -> Optional[B]:
if x is None:
return None
return f(x)
option_map(None, str) # -> None
option_map(3, str) # -> "3"
v: Optional[int] = option_map(3, str) # ERROR: int にはならない
33. Anyの回避 (ジェネリクス)–typing
CARとCDR -Wikipediaより:
T = TypeVar("T")
@dataclass
class Cons(Generic[T]):
car: T
cdr: Optional[Cons[T]] = None
def to_list(self) -> list[T]: # 効率は良くないが短く書く場合
if self.cdr is None:
return [self.car]
return [self.car] + self.cdr.to_list()
l: Cons[int] = Cons(1)
# Cons(car=1, cdr=None)
l.cdr = Cons(2)
# Cons(car=1, cdr=Cons(car=2, cdr=None))
l.to_list()
# [1, 2]
l.cdr.cdr = Cons("string") # NG
34. dictの回避 –typing
基本的には dataclass_json でシリアライズ・デシリアライズする
TypedDict で cast して迂回することも可能
dic = {
"id": 1,
"name": "my name",
"project_ids": [5, 6, 10]
}
class UserDict(TypedDict):
id: int
name: str
project_ids: list[int]
user = cast(UserDict, dic)
id: str = user["id"] # 型エラー!: id フィールドは str ではない
user["projects"] = [1, 2, 3] # 未定義フィールドエラー!
user["project_ids"]["myid"] # 型エラー!: "myid" は int ではない
35. 型検査の限界 (Json型の定義)–typing
Json = dict | list | str | int | float | bool | None
# 正確にはこうなるが、Python 3.10 現在では再帰的型定義が書けない
Json = dict[str, Json] | list[Json] | str | int | float | bool | None
36. 型検査の限界 (型検査の曖昧性)–typing
🤔
m: list[float] = [1.0, 2, True] # OK
[type(x) for x in m]
# [<class 'float'>, <class 'int'>, <class 'bool'>]
[x * x for x in m]
# [1.0, 4, 1]
[type(x * x) for x in m]
# [<class 'float'>, <class 'int'>, <class 'int'>]
37. 38. 39. 40. 41. 42. 43. 暗黙の CPU放棄 –async/await
await がある箇所では CPU放棄が発生する可能性がある
放棄された CPUを使って別のタスクが動作可能 (並行処理)
async def async_sleep5() -> None:
print(f"async: start: {time.perf_counter()}")
await asyncio.sleep(5) # CPU を放棄する
print(f"async: end: {time.perf_counter()}")
async def do_async() -> None:
await asyncio.gather(
async_sleep5(),
async_sleep5(),
)
asyncio.run(do_async()) # 並列 (並行) に実行
# async: start: 81477.041671433
# async: start: 81477.041722131
# async: end: 81482.045057883
# async: end: 81482.045123142
async def sync_sleep5() -> None:
print(f"sync: start: {time.perf_counter()}")
time.sleep(5) # CPU を放棄しない
print(f"sync: end: {time.perf_counter()}")
async def do_sync() -> None:
await asyncio.gather(
sync_sleep5(),
sync_sleep5()
)
asyncio.run(do_sync()) # 直列に実行
# sync: start: 81482.045933061
# sync: end: 81487.051035888
# sync: start: 81487.051202991
# sync: end: 81492.056521034
44. Executorと待ち合わせ処理 –async/await
一体誰が待ち合わせ処理(コルーチンの実行)をしているの? → Executor
デフォルトではメインスレッドで並行処理 (1:N モデル)
並列・並行処理を行う Executor も使用可能 (M:N モデル)
ThreadPoolExecutor
ProcessPoolExecutor
どうやって待ち合わせしてもらう(CPUを放棄する)の?
fdや socket などは await 可能な API があるのでそれを使う
ブロックしてしまう場合に勝手に CPUを放棄してくれる
自分で待ち合わせ処理を書くこともできるが、普通そんなことは不要なはず
45. 46. select()との比較 –async/await
select() は fdの待ち合わせ(+ タイムアウト)
async/await では「一連の処理」をまとめて待ち合わせ
多数のキーワードを Googleで検索して最上位でヒットしたページを並列処理で保存した
い…
select() でシングルポイントで socket を切り替えながら待つのは大変
async/await なら「検索して最上位でヒットしたページを保存」という一連の処理を同
時にスケジュールできる
async/await をサポートする言語で select() を使うことはもうありません。
47.