15

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.

2
  • Why not just a string - function_pointer: "function"? Commented Jan 1, 2015 at 18:44
  • This question is similar to: How can I specify the function type in my type hints?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jul 23, 2024 at 4:39

4 Answers 4

11

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This seems to be a very good, straight forward and easy to remember approach. I'll go the way with the types package.
9

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:
    # Body 

It 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

This should be the accepted answer. It allows to document arguments and return, and it uses a standard providing by "typing".. so its made for this purpose.
Current docs link: Annotating callable objects
4

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

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.