Python ã®åã·ã¹ãã ã®ä¸ã§ Immutable 㪠Python ããã°ã©ã ãä½ã
ã¾ããã
ä»å¹´ã® PyCon JP 2020 ã«ã¦ãPython 3.9 æ代ã®åå®å ¨ãª Python ã®æ¥µãæ¹ãã¨ããã¿ã¤ãã«ã§ç»å£ããã¦ããã ãã¾ããæ¬ç¨¿ã¯ãçºè¡¨ã®è£è¶³ã¨ãªããåãã³ãã使ã£ã¦ Immutable 㪠Python ãå®ç¾ããæ¹æ³ãã«ã¤ãã¦ç´¹ä»ãããã®ã§ãã
Python ã®åãã³ã
Python ã«ã¯ãåãã³ããã¨ããæ©è½ããããåãããã°ã©ã å ã«å®£è¨ãããã¨ãã§ãã¾ãã
age: int = 28 name: str = 'Bruce Wayne'
Python ã¯åçåä»ãè¨èªã§ããããããã®æ å ±ã¯ã©ã³ã¿ã¤ã (å®è¡æ)ã«ã¯ãã¾ãæå³ããªãã®ã§ããã mypy ãªã©ã®åãã§ãã¯ãã¼ã«ãã¤ããã¨ãåã®èª¤ãããã§ãã¯ãããã¨ãã§ãã¾ãã
def check_batman(name: str) -> bool: return name == 'Bruce Wayne' age = 28 check_batman(28) # NG: æåååã®å¼æ°ã« int ãå ¥ãã¦ãããã
ãã¦ããã®æ©è½ãã¤ããã¨ã list ã set ã®ãã㪠mutable (è¦ç´ ãæ¸ãæãå¯è½) ãªãã¼ã¿æ§é ã§ãã£ã¦ããåã·ã¹ãã ä¸ã«ããã¦ã¯ imutable ãªãã®ã¨ãã¦æ±ããã¨ãã§ãã¾ããã©ã³ã¿ã¤ã æã¯åºæ¬çãªãã¼ã¿æ§é ã§ãã list ã set ãªã©ã使ãç¶ããªããããåã®ãã§ãã¯æã ãæ¸ãæããé²ããã¨ãã§ããã®ã§ãã
Immutable Python ã¨ã¯
ä¾ãã°ã list ã immutable ã«ãããã¨ããã®ã¯ããããããã¨ãé²ãã®ãç®çã§ãã
def check_list(li: list): li.append('fuga') # â åæã«æ¸ãæããªãã§ããããã users = [] if check_list(users): # â æå³ããæ¸ãæãã£ã¦ãã¾ã ...
ãããã«ãããªã«ãã¨ã¯ããªãã¨æãã¾ãããä¾ãã° numpy ã® shuffle ã JavaScript ã® sort ãªã©ãé åã«å¤æ´ãå ãã¦å«ãªæ°æã¡ã«ãªãã±ã¼ã¹ã¯çµæ§ç´ãã¦ãã¾ãã
ãããã©ã³ã¿ã¤ã (å®è¡æ)æã« Immutable ã«ããæ¹æ³ãããã¾ããååã®æ¸ããè¨äºãã覧ãã ããã
ããããããã¾ã§ãã¼ã¿æ§é ã¨ãã¦ã¯ä¸è¬çãªãã®ã使ãç¶ããããã©ã³ã¿ã¤ã ã®æåãå¤ããã« Immutable ã«ããããã¨ãããã¨æãã¾ããä»å㯠ã¯ã©ã¹ããªã¹ãçã®ãã¼ã¿æ§é ãä¸å¤ãªç¶æ ãä¿ã¤ã㨠ãç®çã¨ããå¤æ°ã®æ¸ãæãé²æ¢ãå¯ä½ç¨å ¨è¬ã®ã³ã³ããã¼ã«ãã©ã³ã¿ã¤ã æã® Immutability ãªã©ã¯ç®çã¨ãã¦ãã¾ããã
Immutable 㪠list ã¨ã¯
ä¾ãã°ãlist ã«å¯¾ããç ´å£çãªå¤æ´ã¯ã次ã®ãããªãã®ãããã¾ãã
name_list.append('New User') name_list[1] = 'Renamed User'
ã¤ã¾ããå¤æ´ã§ããã¡ã½ãããçãã¦ãããããlist ãå¤æ´ã§ãã¦ãã¾ãã®ã§ããéã«ãå¤æ´ã§ããã¡ã½ãããçãã¦ããªã list ãå宣è¨ããã°ããã® list ã¯åã·ã¹ãã ã®ä¸çã«ããã¦ã¯å®è³ª immutable ã§ãã
Protocol ã«ããå宣è¨
Python ã§ã¯ 3.8 ãã Protocol ã¨ãããç¶æ¿ã«ãããªãé¨ååãã宣è¨ã§ããããã«ãªãã¾ãããã¤ã¾ããä½ãç¶æ¿ãã¦ãã(ååçé¨åå)ãããªãã¦ãä½ãæã£ã¦ããã(æ§é çé¨åå)ã§èªåãèªããï¼ãã¨ãããã¨ã§ãã
from typing import Protocol class Vehicle(Protocol): def run(self): ... class BatMobile: def run(self): ... def run_vehicle(v: Vehicle): v.run() run_vehicle(BatMobile()) # ç¶æ¿ãã¦ãªããã©OK
ããã§ãBatMobile 㨠Vehicle ã®éã«ã¯ç¶æ¿é¢ä¿ã¯ããã¾ãã(ååçé¨ååã§ãªã)ããããã run
ã¨ããå
±éã®ã¡ã½ãããæã£ã¦ãã¦ãé¢æ°å
ã§ã¯ãããå¼ã³åºãã¦ãã¾ãããããã£ã¦ãæ§é çé¨ååã¨ãã¦ã¯ OK ãªã®ã§ãã
ã§ã¯ãImmutable 㪠list ã¨ãªããããªæ§é çé¨ååããå®ç¾©ãã¦ã¿ã¾ãããããImmutable 㪠listãã¯ãã'a' in hoge
ãã¨ããfor x in hoge
ãã¨ãã¯ã§ããã®ã«ãã hoge[0] = fuga
ã ã¯ã§ããªããã㪠list ã§ããããã㯠Python ã§ã¯ __contains__
ã __iter__
ã __setitem__
ã¨ãã£ãã¡ã½ããã class ã«å®ç¾©ããã¦ããããã¨ã§å®ç¾ã§ãã¾ãã
from typing import Protocol class ImmutableList(Protocol): def __contains__(self, x): ... def __iter__(self): ... def check_list(li: ImmutableList): print('a' in li) # OK for x in li: # OK ... li.append('fuga') # NG users: ImutableList = [] if check_list(users): ...
ä»å㯠ImmutableList ã¨ããã®ãä½ã£ã¦ã¿ã¾ãããã Python å ¬å¼ã§ç¨æããã¦ãã ã®ã§ãããã使ãã¾ãããã
from typing import Sequence def check_list(li: Sequence): print('a' in li) # OK for x in li: # OK ... li.append('fuga') # NG users: ImutableList = [] if check_list(users): ...
åæ§ã«ãMapping (immutable 㪠dict ç¸å½)ãSet(immutable 㪠set ç¸å½)ãªã©ãç¨æããã¦ãã¾ãã
Immutable 㪠class
dataclass(frozen=True) ã NamedTuple ãã¤ããã¨ãmypy ã¯ãã§ãã¯ãã¦ããã¾ãããã¡ãããã©ã³ã¿ã¤ã ä¸ã§ã immutable ã«ãªãã¾ãã
from dataclasses import dataclass @dataclass(frozen=True) class User: name: str batman = User(name='Bruce Wayne') batman.name = 'Dick Grayson' # NG
ãã®æ¹å¼ã®å¾®å¦ãªæ¹æ³
__contains__
ãæã£ã¦ãããã©ããã§ãã宣è¨ã§ããªãã®ã§ããçã« set ã dict ãã»ãããimmutable ã§ãã¨ããã±ã¼ã¹ã«ã¯ä½¿ãã¾ãããä¾ãã°ã x in []
㨠x in {}
ã§ã¯ãè¨ç®éãéãã®ã§ãcontains ãæã£ã¦ãã¦ã list ã¯å°ããã¨ããå ´åã«ã¯ä½¿ãã¾ããã
åã®ä¸ã§ Immutable ãªãã¼ã¿æ§é ã®ã¡ãªãã
ã¨ãããã¾ã§æ¸ãã¦ãImmutable 㪠Python ã£ã¦æå³ããã®ï¼ãã¨ããçåãæãããããããã¾ããããã®ã¡ãªããã¯ï¼ã¤ããã¾ãã
ä¸ã¤ãã¯ãæå³ããªãå¯ä½ç¨ãçºçãããªãï¼å®å ¨ãªããã°ã©ã ãä½ãï¼ã¨ãã観ç¹ã§ãã
ï¼ã¤ãã®çç±ã¯ãlist ãªã©ã®ã¸ã§ããªã¯ã¹ã¯ãå ±å¤ã§ã¯ãªãã¨ãããã¨ã§ããä¾ãã°ããç¬ãªã¹ããã¯ãåç©ãªã¹ããã¨ãã¦æ±ããã§ããããï¼
from typing import List class Animal: ... class Dog(Animal): # ç¶æ¿é¢ä¿ã«ãã ... def check_animal(animal: List[Animal]): ... dogs = [Dog()] check_animal(dogs) # NG: List[Dog]ã¯List[Animal]ã¨ãã¦æ±ããªã!
å®ã¯ããç¬ãªã¹ããã¯ãåç©ãªã¹ããã¨ãã¦æ±ããã¨ã¯ã§ãã¾ããããªããã¨ããã¨ã check_animal ã®ä¸ã§åæã«ãããããªã¹ããçã«æ¸ãæãã¦ãã¾ãã¨ãã§ããããã§ããéã«ãæ¸ãæããããªãããã«ãã¦ãããã°ããç¬ãªã¹ããããåç©ãªã¹ããã¨ãã¦æ±ããã¨ãã§ãã¾ãã
from typing import Sequence class Animal: ... class Dog(Animal): # ç¶æ¿é¢ä¿ã«ãã ... def check_animal(animal: Sequence[Animal]): # List ãã Sequence ã«å¤ããã ã ... dogs = [Dog()] check_animal(dogs)
ããç¨åº¦ Python ã§åãã³ããã¡ããã¨æ¸ãã¦ããã¨ãã¸ã§ããªã¯ã¹ã®ãã®ãããã®æåã«å¼ã£ããããã¨ããããã¨æãã¾ãã
(追è¨) ï¼ã¤ãã®ã¡ãªããã¨ãã¦ããããã©ã«ãå¼æ°ã«ãã¥ã¼ã¿ãã«ãªãã®ãå ¥ãã¦ãã°ããã¨ãããã¨ããªããªãã¾ããããã©ã«ãå¼æ°ã«ã¯ [] ãªã©ã¯å ¥ãããNone ãªã©ã®ã¤ãã¥ã¼ã¿ãã«ãªãã®ã ãå ¥ããã¹ãã¨ãããã©ã¯ãã£ã¹ãããã¾ãããåãã§ãã¯ããããªãã°ãã®ãã©ã¯ãã£ã¹ã¯æå³ããªããªãã¾ãã
ãããããã¨ã§ã pic.twitter.com/rfT4RrnN5B
— å°ç¬ åã¿ã¤ã / JXé信社 / 71.2ã (@YAMITZKY) 2020å¹´8æ26æ¥
宣ä¼
...ã¿ãã㪠Python ã®åã®è©±ããPyCon JP 2020 ã«ã¦ãPython 3.9 æ代ã®åå®å ¨ãª Python ã®æ¥µãæ¹ãã¨ããã¿ã¤ãã«ã§ 8/28(é) 11:50ã çºè¡¨ãã¾ãããã±ãããè²·ã£ã¦ãªãæ¹ããYouTube ã«ã¦çé ä¿¡ãè¦ããã¨ã®ãã¨ã§ãã
ååã® id:shinyorke ãåæ¥ 16:50ã ãã¹ãã¼ããã¼ã¿ãç¨ããç¹å¾´éã¨ã³ã¸ãã¢ãªã³ã°ã¨éçé¸æã®æ績äºæ¸¬ - Pythonã¨Rãè¡ã£ããæ¥ãããã¨ããã¿ã¤ãã«ã§çºè¡¨ãããã¾ãã®ã§ããã¡ããæ¯éã覧ãã ããï¼