kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

16章 計算幾何学 (続き)

あとはやりながら必要になったら調べていこう

ということでライブラリづくりの続き

ちょっとだけ型をつけてみる

class Point():
    def __init__(self, x: float=0.0, y: float=0.0) -> None:
        self.x: float = x
        self.y: float = y

    def __eq__(self, other: Point) -> bool:
        return self.x == other.x and self.y == other.y

__init__でself.xはfloatだって言ったことは
__eq__の中でも覚えててくれるのかなあ
さらにはother.xもfloatなんだってことはわかってる?

mypyにかけてみる

$ mypy shape.py
shape.py:6: error: Argument 1 of "__eq__" incompatible with supertype "object"
shape.py:6: note: It is recommended for "__eq__" to work with arbitrary objects, for example:
shape.py:6: note:     def __eq__(self, other: object) -> bool:
shape.py:6: note:         if not isinstance(other, Point):
shape.py:6: note:             return NotImplemented
shape.py:6: note:         return <logic to compare two Point instances>

あそうか
otherにPoint型が入ってるとは限らないもんね
コードの例までつけてくれて・・・
ん そうか?
型チェックするんだからPointが入らないようなコードは事前に
チェックしてくれて、実行時に自分でチェックしなくていいように
してくれたほうがうれしい気もするけど?

でもこのコード、pythonが通してくれない

$ shape.py
Traceback (most recent call last):
  File "./shape.py", line 4, in <module>
    class Point():
  File "./shape.py", line 9, in Point
    def __eq__(self, other: Point) -> bool:
NameError: name 'Point' is not defined

そういえば前方参照についても書いてあったな
えーと、文字列にするのか
すごい解決策だな
こういうことか

    def __eq__(self, other: 'Point') -> bool:
        return self.x == other.x and self.y == other.y

どれどれ

$ shape.py
$

通ったな
でもmypyさんが同じエラーを出してくる
言われたとおりにするか
いやそのまえに型ヒントだけ変えてみよう

    def __eq__(self, other: object) -> bool:
        return self.x == other.x and self.y == other.y

pythonは通してくれる
mypyは

$ mypy shape.py
shape.py:10: error: "object" has no attribute "x"
shape.py:10: error: "object" has no attribute "y"

そうか、object型にはxもyもないもんな
ってじゃあどうなるのよ
こうしたら解決するっていうの?

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y

解決した

$ shape.py
$ mypy shape.py
$

賢いな
型だけ見てるんじゃなくて、
not isinstance(other, Point):じゃないってことから
otherはPoint型だ、ってことまで理解してるのか
Typed Racketでも似たようなことしてたな

そこまで理解してるってことは↓くらいは余裕で理解してるんだろうな

__init__でself.xはfloatだって言ったことは
__eq__の中でも覚えててくれるのかなあ
さらにはother.xもfloatなんだってことはわかってる?