-
To avoid repeating myself too much, I sometimes like to create helper functions that return a new function which is intended to be used as a method. The "method creating function" would typically take in some arguments. It would then create a new function that receives What I'm looking for, is a way to:
Using CallableTyping this using from collections.abc import Callable
from typing import Any
def create_int_converter() -> Callable[[Any, str], int]:
return lambda self, s: int(s)
class ClassWithDynamicallyCreatedMethod:
convert_to_int = create_int_converter()
o = ClassWithDynamicallyCreatedMethod()
converted: int = o.convert_to_int("123")
print(repr(converted)) Mypy: ✅ Using callback protocol without extra self argumentHowever, I'd like to define overloads for the generated method. To do this, I thought I could build on the concept of "Callback protocols" as mentioned in PEP 544: from typing import Any, Protocol
class ConverterProtocol(Protocol):
def __call__(self, s: str) -> int: ...
def create_int_converter() -> ConverterProtocol:
def converter(self: Any, s: str) -> int:
return int(s)
return converter
class ClassWithDynamicallyCreatedMethod:
greeting = "Hi there!"
convert_to_int = create_int_converter()
o = ClassWithDynamicallyCreatedMethod()
converted: int = o.convert_to_int("123")
print(repr(converted)) Mypy: ❌ Mypy error:
Using callback protocol with extra self argumentI tried experimenting with adding an explicit from typing import Any, Protocol
class ConverterProtocol(Protocol):
def __call__(self_, self: Any, s: str) -> int: ...
def create_int_converter() -> ConverterProtocol:
def converter(self: Any, s: str) -> int:
return int(s)
return converter
class ClassWithDynamicallyCreatedMethod:
greeting = "Hi there!"
convert_to_int = create_int_converter()
o = ClassWithDynamicallyCreatedMethod()
converted: int = o.convert_to_int("123")
print(repr(converted)) Mypy: ❌ Mypy error:
ThoughtsI first thought this would be a bug in Mypy. And maybe it is? But I'm also thinking there is a nuanced difference between how a function and a callable user object are treated with respect to the first I'm starting to think that the "callback protocol" approach is not usable for this usecase, because an instance of a class with a The following two Mypy issues may be related: python/mypy#708 and python/mypy#5485 but I don't think they address the inconsistencies the latter two examples demonstrate? I'll consider opening issues on that later. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 8 replies
-
That's correct. When Python looks up a method from an instance, it calls Consider this, for example:
For function objects, the To tell mypy that your object isn't just a callable, but a method, you need to explain to mypy that |
Beta Was this translation helpful? Give feedback.
That's correct. When Python looks up a method from an instance, it calls
__get__
to get a method object, which it then__call__()
s. If there is no__get__
, the object is called as is, without passingself
.Consider this, for example: