16章 計算幾何学 (続き3)
この間
>>> greeting(1) TypeError: must be str, not int
書いただけで使えるみたい
って書いたけど完全に勘違いだな
これはただのランタイムエラーだ
いろいろ見たり試したりして
Polygon = List[Point]
って書けることはわかったけど
結局Polygonクラスを作ることになりそうな気もしている
などなど思いつつ続き
Pointの演算子を定義する
double x, y;
Point operator + ( Point &p ) {
return Point(x + p.x, y + p.y)
}
なにこのxとy
C++で演算子のオーバーロードをしてるんだろうけど
class Point { ... }
を省略して書いてるってことかな
まあいいや言いたいことはわかる
class Point:
...
def __add__(self, other: 'Point') -> 'Point':
return Point(self.x + other.x, self.y + other.y)
こうですね
$ python3 -i shape.py
>>> Point(1, 2) + Point(3, 4)
Point(4, 6)
引き算にかけ算
def __sub__(self, other: 'Point') -> 'Point':
return Point(self.x - other.x, self.y - other.y)
def __mul__(self, k: float) -> 'Point':
return Point(self.x * k, self.y * k)
これだとPoint(1, 2) * 2
とは書けても
2 * Point(1, 2)
とは書けないな
>>> Point(1, 2) * 2
Point(2, 4)
>>> 2 * Point(1, 2)
TypeError: unsupported operand type(s) for *: 'int' and 'Point'
なんかあった気がする
こうだ
def __rmul__(self, k: float) -> 'Point':
return self * k
どうだ
>>> 2 * Point(1, 2)
Point(2, 4)
できた
次はノルムと大きさ
サンプルは関数で書いてあるけど、Pointクラスのメソッドにしよう
特に難しいところはない
Point全体のサンプルと見比べて__eq__
を書き換え、
__truediv__
と__lt__
を追加
__lt__
ってこんなふうに定義するんだ・・・と思ったけど
bool operator < (const Point &p) const {
return x != p.x ? x < p.x : y < p.y
}
==
を差がEPSより小さい、ってやるんだったらここもそうすべきでは?
などと考えつつPointクラスはこうなりました
class Point:
EPS = 1e-10
def __init__(self, x: float=0.0, y: float=0.0) -> None:
self.x = x
self.y = y
def __eq__(self, other: object) -> bool:
if not isinstance(other, Point):
return NotImplemented
return abs(self.x - other.x) < Point.EPS and \
abs(self.y - other.y) < Point.EPS
def __add__(self, other: 'Point') -> 'Point':
return Point(self.x + other.x, self.y + other.y)
def __sub__(self, other: 'Point') -> 'Point':
return Point(self.x - other.x, self.y - other.y)
def __mul__(self, k: float) -> 'Point':
return Point(self.x * k, self.y * k)
def __rmul__(self, k: float) -> 'Point':
return self * k
def __truediv__(self, k: float) -> 'Point':
return Point(self.x / k, self.y / k)
def __lt__(self, other: 'Point') -> bool:
return self.y < other.y \
if abs(self.x - other.x) < Point.EPS \
else self.x < other.x
def __repr__(self) -> str:
return "Point({}, {})".format(self.x, self.y)
def norm(self):
return self.x * self.x + self.y * self.y
def abs(self):
return sqrt(self.norm())