まず質問文の実装はVector同士でも問題があります。本筋とはさほど関係ありませんが、後の説明がややこしくなるので言っておきます。
端的に言うと、__add__
では状態が変化しないことが期待されるので、新たなオブジェクトを生成して返すようにしておいた方が良いです。
python
1 def __add__(self, v):
2 return Vector(self.x + v.x, self.y + v.y)
3
さて、本題です。
まず、引数の型を見て分岐させるようにします。
python
1 def __add__(self, v):
2 if isinstance(v, Vector):
3 return Vector(self.x + v.x, self.y + v.y)
4 else:
5 # 何かする
ナイーブなやり方としては、こういう感じとか。
python
1class Vector:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5 def __add__(self, v):
6 if isinstance(v, Vector):
7 return Vector(self.x + v.x, self.y + v.y)
8 elif isinstance(v, (int, float, complex)):
9 return Vector(self.x + v, self.y + v)
10 else:
11 return NotImplemented
12
13 def __repr__(self):
14 return "Vector(x={}, y={})".format(self.x, self.y)
こうすると、
python
1v = Vector(1, 2)
2print(v) # ok
3print(v + v) # ok
4print(v + 1) # ok
5print(1 + v) # TypeError: unsupported operand type(s) for +: 'int' and 'Vector'
となるので、__radd__
を形式的に作ると良いでしょう。
python
1class Vector:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5
6 def __add__(self, v):
7 if isinstance(v, Vector):
8 return Vector(self.x + v.x, self.y + v.y)
9 elif isinstance(v, (int, float, complex)):
10 return Vector(self.x + v, self.y + v)
11 else:
12 return NotImplemented
13
14 def __radd__(self, v):
15 return self.__add__(v)
16
17 def __repr__(self):
18 return "Vector(x={}, y={})".format(self.x, self.y)
19
これくらいあればごく基本的な加算だけはだいたい不満感なく行えるかと思います。ちょっと複雑なケースを想定するとまだまともに動かない部分もあると思います(把握していませんが)。
本気で実装するのであれば、言語リファレンスのデータモデルをよく読みながら取り組むことをおすすめします。
3. データモデル — Python 3.8.1rc1 ドキュメント