Created
June 8, 2026 01:06
-
-
Save mypy-play/2fb651ddee58d4176237eb3c3dfb7c1a to your computer and use it in GitHub Desktop.
Shared via mypy Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from typing import Callable, Protocol | |
| ### Example 1: Works as intended. The method is decorated and is | |
| ### callable as usual. | |
| def decorate_method[T](method: Callable[[T], None]) -> Callable[[T], None]: | |
| def _inner(_self: T) -> None: | |
| print('Decorated!') | |
| method(_self) | |
| return _inner | |
| class A: | |
| @decorate_method | |
| def my_method(self) -> None: | |
| print('my_method') | |
| # Explicit call syntax. Fine. | |
| print(A.my_method(A())) | |
| # Instance call syntax. Fine. | |
| print(A().my_method()) | |
| ### Example 2: Instead of using Callable[[T], None], an equivalent | |
| ### protocol is declared. This is equivalent at runtime but mypy | |
| ### rejects it. | |
| class MyCallable[T](Protocol): | |
| def __call__(self, _self: T, /) -> None: | |
| ... | |
| def decorate_method_1[T](method: MyCallable[T]) -> MyCallable[T]: | |
| def _inner(_self: T) -> None: | |
| print('Decorated!') | |
| method(_self) | |
| return _inner | |
| class B: | |
| @decorate_method_1 | |
| def my_method(self) -> None: | |
| print('my_method') | |
| # Explicit call syntax. Fine. | |
| print(B.my_method(B())) | |
| # Instance call syntax. Rejected by mypy (Too few arguments to | |
| # __call__) but works at runtime. | |
| print(B().my_method()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment