Pythonのクラスで謎の現象
こんなクラス作ってですね
class Point:
def __init__(self, x: float=0.0, y: float=0.0) -> None:
self.x = x
self.y = y
def __repr__(self) -> str:
return "Point({}, {})".format(self.x, self.y)
class Segment:
def __init__(self, p1: Point = Point(), p2: Point = Point()) -> None:
self.p1: Point = p1
self.p2: Point = p2
def __repr__(self) -> str:
return "Segment({}, {})".format(self.p1, self.p2)
Segmentのオブジェクトをふたつ作って
$ python3 -i shape.py
>>> s1 = Segment()
>>> s2 = Segment()
片方を変更すると
>>> s1.p1.x = 1.0
>>> s1
Segment(Point(1.0, 0.0), Point(0.0, 0.0))
もう片方も変わってしまうという現象が!
>>> s2
Segment(Point(1.0, 0.0), Point(0.0, 0.0))
でもs1とs2が同じオブジェクトというわけではない
>>> print(s1 is s2)
False
s1.p1とs2.p1が同じオブジェクトだったという
>>> print(s1.p1 is s2.p1)
True
__init__
のPoint()
が1回しか呼ばれずに
__init__
を呼ぶたびに使い回されてるってわけか
def __init__(self, p1: Point = Point(), p2: Point = Point()) -> None:
そういえばEffective Pythonに書いてあった気がするわー
はまったわー
こういうことか
def __init__(self, p1: Point = None, p2: Point = None) -> None:
self.p1: Point = Point() if p1 is None else p1
self.p2: Point = Point() if p2 is None else p2
どうだ
python3 -i shape.py
>>> s1 = Segment()
>>> s2 = Segment()
>>> s1.p1.x = 1.0
>>> s1
Segment(Point(1.0, 0.0), Point(0.0, 0.0))
>>> s2
Segment(Point(0.0, 0.0), Point(0.0, 0.0))
おk