Pythonの文法キャッチアップノート。
クラス
Python において、クラスもオブジェクトである。
継承が何も定義されていない場合は、objectを継承している
class Foo: pass
class Foo(object): pass
プロパティ
クラス内で定義された変数は、クラス属性
特殊属性
クラスのメタ情報にアクセスするためのプロパティ。 __xx__
の形式で定義されている。
__name__
__module__
__dict__
__bases__
__doc__
__annotations__
class Foo: """ Fooはbarをhogeするクラス """ bar: int = 1 foo = Foo() foo.__class__.__name__ # 'Foo' foo.__class__.__module__ # '__main__' foo.__class__.__dict__ # mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}) foo.__class__.__bases__ # (<class 'object'>,) foo.__class__.__doc__ # 'Fooはbarをhogeするクラス' foo.__class__.__annotations__ # {'bar': <class 'int'>}
特殊メソッド
itmediaさんのサンプルコードを使わせてもらってます。
class Foo: def __new__(cls): print('__new__') self = super().__new__(cls) # インスタンス生成を行う典型的なコード self.attr = 'set in __new__' # ここでしかできない初期化処理を書いてもよい return self # 生成したインスタンスを返す def __init__(self, name='foo'): print('__init__') self.name = name # インスタンスの初期化処理 def __del__(self): #super().__del__() # 基底クラスに__del__メソッドがあれば必ず呼び出す print('__del__') # インスタンスが破壊されるときに行う処理 foo = Foo() # '__new__'と'__init__'が表示される print('foo.attr:', foo.attr) # 'foo.attr: set in __new__' bar = foo print('bar.name:', bar.name) # 'bar.name: foo' print('del foo') # この時点ではまだ生成したインスタンスには別名がある del foo print('del bar') del bar # '__del__':この時点でインスタンスを束縛する名前がなくなる
__repr__
: オブジェクトを表す「公式な」文字列。これは同じ値のオブジェクトを再生成するのに使える、有効な Python 式のようなものであるべきです
とドキュメントに書かれているように、evalで呼び出して同じオブジェクトが生成されるのがいい。__str__
: オブジェクトを表す「非公式な」文字列__bytes__
: bytesで返されるオブジェクトのバイト文字列表現。.encode('utf-8')
した値を返すとbytes型で返せる。 (適切な環境が与えられれば) 。未実装で呼び出されるとエラー__format__
: format()等の関数で呼び出される、オブジェクトのフォーマット化された文字列表現。未実装で呼び出されるとエラー
class Person: def __init__(self, name: str, age: int): self.name = name self.age = age def __repr__(self): return f"Person(name='{self.name}', age={self.age})" def __str__(self): return '%sという名前の%i歳の人' % (self.name, self.age) def __bytes__(self): return 'person'.encode('utf-8') def __format__(self, fmt): if len(fmt) == 0: return str(self) return fmt.format(self.name) p = Person(name="anderiens", age=25) print(p) # anderiensという名前の25歳の人 print(repr(p)) # Person(name='anderiens', age=25) print(bytes(p)) # b'person' print(format(p, '{} hoge')) # anderiens hoge # reprをevalする print(eval(repr(p))) # anderiensという名前の25歳の人
比較
__lt__
: x < yで呼び出される__le__
: x <= yで呼び出される__eq__
: x == yで呼び出される__ne__
: x != yで呼び出される__gt__
: x > yで呼び出される__ge__
: x >= yで呼び出される__hash__
__bool__
https://www.yoheim.net/blog.php?q=20171002 のコードを参考にさせてもらっています。
class Item: """ 価格順で並び替えできる """ def __init__(self, price: int): self.price = price def __eq__(self, other): if not isinstance(other, Item): return NotImplemented return self.price == other.price def __lt__(self, other): if not isinstance(other, Item): return NotImplemented return self.price < other.price def __ne__(self, other): return not self.__eq__(other) def __le__(self, other): return self.__lt__(other) or self.__eq__(other) def __gt__(self, other): return not self.__le__(other) def __ge__(self, other): return not self.__lt__(other) item1 = Item(price=100) item2 = Item(price=200) if item1 > item2: print('item1 is more expensive than item2.') else: print('item2 is more expensive than item1.')