*Memo:
- My post explains type hints (1).
- My post explains type hints (2).
- My post explains type hints (3).
- My post explains type hints (4).
- My post explains type hints (5).
Callable and Protocol can be used for a function as shown below:
*Memo:
-
Callablecan specify function parameter and return types, doing less thanProtocol:- The 1st argument is
paramtypes(Required:-Type:list(Type) orellipsis):- It's a list of one or more parameter types.
-
...(but notEllipsis) can be used to accept the zero or more arguments of all types but it shouldn't be used because it's too gereral:-
...is different from Any which accepts the one argument of all types.
-
- Don't use
paramtypes=.
- The 2nd argument is
returntype(Required-Type:Type)):- It's a return type.
- Don't use
returntype=.
- The 1st argument is
-
Protocolcan specify a function signature, doing more thanCallable:- It has no arguments.
- It can be used by extended.
- The method with the signature which you want to specify should be defined in the extended class:
- Specific parameter default values and body aren't necessary because they affect nothing but they can still be set if you want.
-
...shows the presence of default values and body but specific ones aren't there: - Even if specific parameter default values can be set, their types must be suitable.
-
-
The static method without
selfcan also be used.
- For
*argswithCallable, the specific type[*tuple[type, ...]]can be used but for**kwargswithCallable, there is no specific type so only the general type...can be used, accepting the zero or more arguments of all types, which isn't good so for**kwargs,Protocolshould be used.
<With normal parameters>:
from collections.abc import Callable
from typing import Protocol
def func(x: int, y: int | float = 4) -> str:
return f'x+y={x+y}'
print(func(5)) # No error
print(func(x=5)) # No error
print(func(5, 2)) # No error
print(func(x=5, y=2)) # No error
v1: Callable[[int, int | float], str] = func
# v1: Callable[..., str] = func
print(v1(5)) # Error
print(v1(x=5)) # Error
print(v1(5, 2)) # No error
print(v1(x=5, y=2)) # Error
class MyType(Protocol):
def __call__(self, x: int, y: int | float = ...) -> str: ...
# @staticmethod
# def __call__(x: int, y: int | float = ...) -> str: ...
v2: MyType = func
print(v2(5)) # No error
print(v2(x=5)) # No error
print(v2(5, 2)) # No error
print(v2(x=5, y=2)) # No error
<With *args>:
from collections.abc import Callable
from typing import Protocol
def func(*args: int) -> str:
return f'{args}'
print(func(0, 1, 2)) # No error
v1: Callable[[*tuple[int, ...]], str] = func
# v1: Callable[..., str] = func
print(v1(0, 1, 2)) # No error
class MyType(Protocol):
def __call__(self, *args: int) -> str: ...
# @staticmethod
# def __call__(*args: int) -> str: ...
v2: MyType = func
print(v2(0, 1, 2)) # No error
<With **kwargs>:
from collections.abc import Callable
from typing import Protocol
def func(**kwargs: float) -> str:
return f'{kwargs}'
print(func(x=0.0, y=1.0, z=2.0)) # No error
v1: Callable[..., str] = func
print(v1(x=0.0, y=1.0, z=2.0)) # No error
class MyType(Protocol):
def __call__(self, **kwargs: float) -> str: ...
# @staticmethod
# def __call__(**kwargs: float) -> str: ...
v2: MyType = func
print(v2(x=0.0, y=1.0, z=2.0)) # No error
<With *args & **kwargs>:
from collections.abc import Callable
from typing import Protocol
def func(*args: int, **kwargs: float) -> str:
return f'{args} {kwargs}'
print(func(0, 1, 2)) # No error
print(func(x=0.0, y=1.0, z=2.0)) # No error
print(func(0, 1, 2, x=0.0, y=1.0, z=2.0)) # No error
v1: Callable[..., str] = func
print(v1(0, 1, 2)) # No error
print(v1(x=0.0, y=1.0, z=2.0)) # No error
print(v1(0, 1, 2, x=0.0, y=1.0, z=2.0)) # No error
class MyType(Protocol):
def __call__(self, *args: int, **kwargs: float) -> str: ...
# @staticmethod
# def __call__(*args: int, **kwargs: float) -> str: ...
v2: MyType = func
print(v2(0, 1, 2)) # No error
print(v2(x=0.0, y=1.0, z=2.0)) # No error
print(v2(0, 1, 2, x=0.0, y=1.0, z=2.0)) # No error
Top comments (0)