0xf

日記だよ

Pythonのtyping.Self型はサブクラスで解決されるときにはサブクラスの型となってしまう

Python 3.11系で導入されたSelf型いいじゃんと思ったけどちょっと挙動が期待と違う。手元は3.12.3。

以下のような簡単なコードを考えてみると、

class State:
    def update(self:Self) -> Self:
        return self

    def hello(self:Self):
        print("abstract state")

class DefaultState(State):
    def hello(self:Self):
        print("hello default state")
    def foo(self:Self):
        print("foo! by default")

class NewState(State):
    def update(self:Self) -> Self:
        return DefaultState()
    def bar(self:Self):
        print("bar! by new state")


a = NewState()
b = a.update() # bはDefaultStateのインスタンス
b.hello()
b.foo()
b.bar() # エラー! barメソッドはDefaultStateには存在しない

まあそれはそうですねという挙動なのだけど、a.update()の戻り値が NewStateに推論されてしまうので入力保管などでは bインスタンスbar が生えて見える。しかし実際には DefaultStateインスタンスが返されているため、b.foo()は機能するが b.bar() はコケるのである。

ここでは State で解決されたかったので惜しい...という。