Pythonã¯è¨èªä»æ§ã¨ãã¦ããã©ã«ãå¼æ°ãåå©ç¨ããããã㯠mutable ãªãã¸ã§ã¯ãã¨ã®çµã¿åããã§å®¹æã«ãã°ãå¼ãèµ·ããã
è¨èªä»æ§
é¢æ°å®ç¾©æã«ããã©ã«ãå¼æ°ãè©ä¾¡ããã¦ç¢ºå®ãï¼=è©ä¾¡ã¯ä¸åº¦ããï¼ããããé¢æ°å¼ã³åºãæã«æ¸¡ãããã
The default values are evaluated at the point of function definition in the defining scope ... The default value is evaluated only once.
- å ¬å¼FQA: ãªããªãã¸ã§ã¯ãéã§ããã©ã«ãå¤ãå ±æãããã®ã§ããï¼
- å ¬å¼ä»æ§: 4.8.1. Default Argument Values
æå³ããªããªãã¸ã§ã¯ãå ±æ
ããã©ã«ãå¼æ°ã« mutable ãªãã¸ã§ã¯ãï¼ä¾: listãã¯ã©ã¹ã¤ã³ã¹ã¿ã³ã¹ï¼ã使ãã¨ãè¨èªä»æ§ã«ãããªãã¸ã§ã¯ãå
±æãèµ·ããã
ããã¯ï¼ä¸è¬çãªï¼ããã©ã«ãå¼æ°ã®ã»ãã³ãã£ã¯ã¹ã¨ä¸è´ããªããããæå³ããªãå
±æã¨ãã¦æ©è½ãã¦ãã¾ãå¯è½æ§ãé«ãã
ãããªæãï¼
from dataclasses import dataclass, field @dataclass class Child: c1: str c2: int c3: int = 1 @dataclass class Parent: a1: int child: Child = Child( c1 = "from parent", c2 = 0) p1, p2 = Parent(1), Parent(2) p1.child.c3 = 100 assert p1.child.c3 != p2.child.c3, f"Different instance should have different number, but `{p1.child.c3}` == `{p2.child.c3}`" print("passed") # AssertionError: Different instance should have different number, but `100` == `100`
解決ç
ã¯ã©ã¹ã®å ´åãPythonæ¨æºã® field(default_factory=lambda: Cls(args))
ã§è§£æ¶ã§ããã
default_factory
ã¯ããã©ã«ãå¼æ°ãå¿
è¦ãªéã«é½åº¦å¼åºããããããããã®å ´ã§ã¤ã³ã¹ã¿ã³ã¹ãçæããå
±æãããªãã
ããã«ããæå³ããªãå
±æãé²ããã
ãããªæãï¼
from dataclasses import dataclass, field @dataclass class Child: c1: str c2: int c3: int = 1 @dataclass class Parent: a1: int child: Child = field(default_factory=lambda: Child( c1 = "from parent", c2 = 0)) p1, p2 = Parent(1), Parent(2) p1.child.c3 = 100 assert p1.child.c3 != p2.child.c3, f"Different instance should have different number, but `{p1.child.c3}` == `{p2.child.c3}`" print("passed") # passed
ç³è¡£æ§æ
ä¸è¨ã®è§£æ±ºçã¯åé¡ã解決ã§ããããè¨è¿°ãç ©éã«ãªãã
ç§ã¯ä»¥ä¸ã®ãããªç³è¡£æ§æã使ã£ã¦ããï¼
from copy import deepcopy def default(instance): return field(default_factory=lambda: deepcopy(instance))
ãããç¨ãããã¨ã§æ¬¡ã®ããã«ç°¡ç¥åãããï¼
from dataclasses import dataclass, field @dataclass class Child: c1: str c2: int c3: int = 1 @dataclass class Parent: a1: int child: Child = default(Child( c1 = "from parent", c2 = 0)) p1, p2 = Parent(1), Parent(2) p1.child.c3 = 100 assert p1.child.c3 != p2.child.c3, f"Different instance should have different number, but `{p1.child.c3}` == `{p2.child.c3}`" print("passed") # passed