Reputation: 33598
Consider the code:
from enum import Enum, auto
from typing import Self
from typing import List
from multipledispatch import dispatch
from multimethod import multimethod
class Name:
__id: list[str]
def __new__(self, id: list[str]):
self.__id = id
# ...
@multimethod
def prefix(self, other: Self) -> Self:
return self.prefix(other.__id)
# EXCEPTION HERE
@multimethod
def prefix(self, prefix: List[str]) -> Self:
return Name(prefix + self.__id)
@multimethod
def postfix(self, postfix: List[str]) -> Self:
return Name(self.__id + postfix)
Error stack is
Traceback (most recent call last):
File "myfolder\app.py", line 6, in <module>
from my_package import MyClass
File "myfolder\__init__.py", line 13, in <module>
class Name:
File "myfolder\__init__.py", line 50, in Name
@multimethod
^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 257, in __init__
self[signature.from_hints(func)] = func
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 299, in __setitem__
parents = types.parents = self.parents(types)
^^^^^^^^^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 282, in parents
parents = {key for key in list(self) if isinstance(key, signature) and key < types}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 282, in <setcomp>
parents = {key for key in list(self) if isinstance(key, signature) and key < types}
^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 221, in __lt__
return self != other and self <= other
^^^^^^^^^^^^^
File "myfolder\.venv\Lib\site-packages\multimethod\__init__.py", line 218, in __le__
return self.required <= len(other) and all(map(issubclass, other, self))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\work\tools\Python\Python3.11.3\Lib\typing.py", line 466, in __subclasscheck__
raise TypeError(f"{self} cannot be used with issubclass()")
TypeError: typing.Self cannot be used with issubclass()
Why this happended? May I use Self
return type with @multimethod
?
Python version 3.11.3
Upvotes: -1
Views: 28
Reputation: 40778
You cannot use Self
as any type annotation you use must support being used in issubclass()
calls. Some typing constructs are special-cased (such as Union
), but Self
is not among these special-cased types.
If you want to type a parameter as being the type of the class being defined then you can add those methods outside, and after, the main body of the class. When adding methods in such a way use the register()
method instead. For example:
class Name:
@multimethod
def func(self, x: int) -> int:
print('f(int)')
return 123
@Name.func.register
def _(self, x: Name) -> Name:
print('f(Name)')
return Name()
assert Name().func(0) == 123
assert Name().func(Name()).__class__ is Name
Upvotes: 0