Python3.6から3.10までの
およそ5年間の間の進化を振り返る

2022.01.27
みんなのPython勉強会#77

お前だれよ

  • Kei IWASAKI
  • コネヒトのインフラエンジニア
  • 最近はAWSやTerraform, Notionを触ってることが多いです

CMその1

プログラミング入門者向け書籍

スラスラわかるPython第2版
発売中!!

CMその2

Software Design 2022年1月号
第2特集第3章に寄稿しました

本日のお話

  • 先月EOLを迎えたPython3.6がリリースされてから早5年、その間にPythonはどんな進化をしてきたのか振り返ってみようと思います
  • 「この機能はここだったのかー」という発見や「ここはこの機能も入ったんじゃない?」といったツッコミまで含めて、5年間のPythonの進化の振り返りを楽しんでいただけると幸いです

注意事項

  • 3.6 から 3.10 までの変更内容はとてもではないけど30分では網羅的には紹介しきれません!そのため @laughk の主観がかなり入った振り返りになる点はご了承ください 🙇
  • より詳細な内容は What's New in Python — Python 3.10.0b2 ドキュメント をご覧ください

Python3.6 から Python3.10 変化

Python3.6(2016.12.23リリース)

Python3.6(2016.12.23リリース)

主な新機能や変更

  • PEP 498 Literal String Interpolation (f-string 追加)
  • PEP 515 Underscores in Numeric Literals
  • PEP 526 Syntax for Variable Annotations

など

PEP 498 Literal String Interpolation

「f」リテラルと {} でパラメータが直接文字列内に埋め込めるように!(f-string)

f-string なしの例

>>> var = "stapy77"
>>> print("Hello!! {}".format(var))
Hello!! stapy77

f-string を使った例

>>> var = "stapy77"
>>> print(f"Hello!! {var}")
Hello!! stapy77

PEP 515 Underscores in Numeric Literals

数値リテラルの中に _ を混ぜてもることができるようになった。

>>> 123456789
123456789

>>> 123_456_789
123456789

PEP 526 Syntax for Variable Annotations

変数アノテーション文法

3.5までの変数の型ヒント

>>> foo = 10 # type: int
>>> var = {"number": 2} # type: Dict[str, int]
>>> baz = "" # type: str

3.6移行では以下のように記載できるようになった

>>> foo: int = 10
>>> var: Dict[str, int] = {"number": 2}
>>> baz: str

Python3.6(2016.12.23リリース)

その他トピック

  • AWS lambda など、マネージドサービスで Python3系がサポートされはじめた
  • Python3.6 が AWS lambda でサポートされたのは翌年2017年

Python3.7(2018.6.27リリース)

Python3.7(2018.6.27リリース)

主な新機能や変更

  • PEP 557 Data Classes
  • dict オブジェクトの順番が保存されるということが宣言された
  • PEP 545 Python Documentation Translations
  • asyncawait が予約語になった

など

PEP 557 Data Classes

class の機能を持ちつつも、属性はクラス変数アノテーションで表現でき、コンストラクタや __repr____eq__ などのマジックメソッドは自動で生成される

>>> @dataclass
... class Point:
...     x: float
...     y: float
...     z: float = 0.0
...
>>> p = Point(1.5, 2.5)
>>> print(p)
Point(x=1.5, y=2.5, z=0.0)

参考: https://docs.python.org/ja/3/whatsnew/3.7.html#dataclasses

dict オブジェクトの順番が保存されるということが宣言された

https://mail.python.org/pipermail/python-dev/2017-December/151283.html より

PEP 545 Python Documentation Translations

公式ドキュメントの翻訳プロセスが定められ、
日本語・フランス語・韓国語が docs.python.org 配下に追加された

Python3.7(2018.6.27リリース)

その他トピック

  • Python3.7 が AWS lambda でサポートされたのは同年2018年
  • fastapi 一番最初のバージョン 0.1.19 がリリース
  • Django も2系となり、Python2系のサポートが終了した

Python3.8(2019.10.4リリース)

Python3.8(2019.10.4リリース)

  • PEP 572 Assignment Expressions
  • PEP 570 Python Positional-Only Parameters

など

PEP 572 Assignment Expressions

通称セイウチ演算子 := が代入演算子として使えるようになった。

>>> a = "hello stapy77!!!"
>>> if (n := len(a)) > 10:
...     print(f"List is too long ({n} elements, expected <= 10)")
...
List is too long (16 elements, expected <= 10)

PEP570 Python Positional-Only Parameters

位置専用引数の追加。
関数定義の際、引数に / を記載するとその手前の引数は位置専用の引数にできるようになった

>>> def hoge(a, /, b):
...     return a+b
...
>>> hoge(1, b=2)
3
>>> hoge(a=1, b=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: hoge() got some positional-only arguments passed as keyword arguments: 'a'

Python3.8(2019.10.4リリース)

その他トピック

  • Python3.8 が AWS lambda でサポートされたのは同年2019年
  • Pythonの父、Guide van Russom 氏がここで意思決定の立場から引退

など

Python3.9(2020.10.5リリース)

Python3.9(2020.10.5リリース)

主な新機能や変更

  • PEP 584 dict にマージと更新の演算子が追加 (演算子 ||=
  • PEP 585 標準コレクション型の型ヒントにおける総称型 (generics) の使用
  • 標準モジュール zoneinfo が登場
  • PEP 602 CPython adopts an annual release cycle.(リリースサイクルが1年に)

など

PEP584 dict にマージと更新の演算子が追加

>>> x = {"key1": "value1_x", "key2": "value2_x"}
>>> y = {"key1": "value1_y", "key3": "value3_y"}

>>> x | y
{'key1': 'value1_y', 'key2': 'value2_x', 'key3': 'value3_y'}
>>> y | x
{'key1': 'value1_x', 'key3': 'value3_y', 'key2': 'value2_x'}

>>> x |= y
>>> x
{'key1': 'value1_y', 'key2': 'value2_x', 'key3': 'value3_y'}

PEP 585 標準コレクション型の型ヒントにおける総称型 (generics) の使用

簡単に言うなら typing.List, typing.Dict の代わりに list, dict を使うことが推奨されるようになった

PEP 585 標準コレクション型の型ヒントにおける総称型 (generics) の使用

Python3.8

>>> foo: list[str]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
>>> var: dict[str, int]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable

PEP 585 標準コレクション型の型ヒントにおける総称型 (generics) の使用

Python3.9

>>> foo: list[str]
>>> var: dict[str, int]
>>>

標準モジュール zoneinfo が登場

Python3.8 まではタイムゾーン名を扱うには dateutil などのサードパーティーパッケージのが必要だったが、標準でサポートされるようになった。

>>> tokyo = ZoneInfo("Asia/Tokyo")
>>> los_angels = ZoneInfo("America/Los_Angeles")

>>> datetime.now(tokyo)
datetime.datetime(2022, 1, 27, 1, 24, 2, 715974, tzinfo=zoneinfo.ZoneInfo(key='Asia/Tokyo'))

>>> datetime.now(los_angels)
datetime.datetime(2022, 1, 26, 8, 24, 8, 305941, tzinfo=zoneinfo.ZoneInfo(key='America/Los_Angeles'))

PEP602 CPython adopts an annual release cycle.


リリースサイクルが1年に
from: https://www.python.org/dev/peps/pep-0602/

Python3.9(2020.10.5リリース)

  • Python3.9 が AWS lambda でサポートされたのは同年2019年
  • pandas 1.0 リリース

ちなみに

この年に Python2.7 が EOL を迎えた


from: https://www.python.org/doc/sunset-python-2/

Python3.10 (2021.10.4)

Python3.10 (2021.10.4)

主な新機能や変更

  • Better Error Messages
  • PEP634 Structural Pattern Matching (パターンマッチング)
  • PEP604 New Type Union Operator(ユニオン型を X | Y と書けるようになった)
  • PEP613 Explicit Type Aliases (明確な型エイリアスが記載できるようになった)

など

エラーメッセージの改修


詳細は以下のページを参照
https://docs.python.org/ja/3/whatsnew/3.10.html#better-error-messages

PEP634 Structural Pattern Matching

簡単に言ってしまうと、ほかの言語でいう switch 文に近い。
ただし、Python のパターンマッチは match と case で表現する。

match http_status:
    case 400:
        print(f"{http_status}: Bad Request")
    case 404:
        print(f"{http_status}: Not Found")
    case 418:
        print(f"{http_status}: Not Found")

PEP634 Structural Pattern Matching

単純な if, else の置き換えにとどまらず、便利な使い方ができそうな予感

hoge = (x, y)
match hoge:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"y={y}")
    case _:
        raise ValueError("Not a point")

PEP604 New Type Union Operator

ユニオン型(typing.Union)を X | Y と書けるようになった

Python3.9 まで

def square(number: Union[int, float]) -> Union[int, float]:
    return number**2

Python3.10

def square(number: int | float) -> int | float:
    return number**2

PEP613 Explicit Type Aliases

明確な型エイリアスが記載できるようになった

PEP613 Explicit Type Aliases

Python3.9 までも型エイリアスは使えたが、 =(イコール) を使うので
代入なのか型エイリアスの作成なのか区別が付かないことがあった

def type_func() -> None:
    pass

myType = type_func
a: myType

このコードは myType という型エイリアスを定義しているつもりであるが、
mypy を通すと myType は関数と判断されて型チェックがコケる

PEP613 Explicit Type Aliases

Python3.10 からは typing.TypeAlias が登場し、型エイリアスの型として利用でできる。先ほどのコードは以下のようにすれば明示的に型エイリアスとして定義できる

def type_func() -> None:
    pass

myType: TypeAlias = type_func
a: myType

振り返ってみての個人的な感想

  • 実際に振り返ってみるとPython3.6以降もものすごく進化をしている
  • 普段自分が使っていない領域機能を改めて新たな発見があった

参考資料(その1)

参考資料(その2)

参考資料(その3)

ご清聴ありがとうございました

https://connehito.com/recruit/

We are hiring!!