For Python 3, it turned out as a good practise for me, to hint data types for function parameters and return types. For example:
def icecream_factory(taste: str='Banana') -> Ice:
ice = Ice(taste)
ice.add_cream()
return ice
This works perfectly for all simple data types and classes. But now I need to use this with a "function pointer":
class NotificationRegister:
def __init__(self):
self.__function_list = list()
""":type: list[?????]"""
def register(self, function_pointer: ?????) -> None:
self.__function_list.append(function_pointer)
def callback():
pass
notification_register = NotificationRegister()
notification_register.register(callback)
What must be put at the ????? to make clear that a function pointer is required here? I tried function, because type(callback) is <class 'function'>, but the keyword function is not defined.
4 Answers 4
I would use types.FunctionType to represent a function:
>>> import types
>>> types.FunctionType
<class 'function'>
>>>
>>> def func():
... pass
...
>>> type(func)
<class 'function'>
>>> isinstance(func, types.FunctionType)
True
>>>
You could also use a string literal such as 'function', but it looks like you want an actual type object.
1 Comment
use Typing.Callable:
https://docs.python.org/3/library/typing.html
Frameworks expecting callback functions of specific signatures might be type hinted using
Callable[[Arg1Type, Arg2Type], ReturnType].For example:
from typing import Callable def feeder(get_next_item: Callable[[], str]) -> None: # Body def async_query(on_success: Callable[[int], None], on_error: Callable[[int, Exception], None]) -> None: # BodyIt is possible to declare the return type of a callable without specifying the call signature by substituting a literal ellipsis for the list of arguments in the type hint:
Callable[..., ReturnType].
2 Comments
1. Basic idea
Show basic idea of function callback's type in python.
Frameworks expecting callback functions of specific signatures might be type hinted at using
Callable[[Arg1Type, Arg2Type], ReturnType]
In your case, you want to use the function callback() without argument and return. So it will be Callable[[], None]
2. The code can work
I improve your code to support the above idea.
Then, you can run this code and the result will be correct.
from typing import Callable
class NotificationRegister:
def __init__(self):
self.__function_list:List[Callable[[],None]] = list()
def register(self, function_pointer: Callable[[], None]) -> None:
self.__function_list.append(function_pointer)
def callback():
pass
notification_register = NotificationRegister()
notification_register.register(callback)
3. More detail to learn
More information here gives you more idea about how to use a different type of function callback in python.
The document of Callable is in the following, but using from typing import Callable is better than using from collections.abc import Callable in my python 3.7 environments.
So I suggest you can use typing instead of collections.abc if your environment is python3.7.
enter image description here
If you want to learn more, then you can read this full document https://docs.python.org/3/library/typing.html
Comments
One approach may be to use collections.abc.Callable:
>>> import collections.abc
>>> def f(): pass
>>> isinstance(f, collections.abc.Callable)
True
This is intended for all objects that implement __call__. This is quite broad as it'll also be True for methods of instances or other objects that happen to implement __call__. But this may be what you intend - it depends on whether you only wish to accept functions or also other callable objects.
function_pointer: "function"?