How can I specify the function type in my type hints?

PythonPython 3.xType HintingMypyPython Typing

Python Problem Overview


How can I specify the type hint of a variable as a function type? (See also: PEP 483.)

import typing

def my_function(func: typing.Function):
    func()

Python Solutions


Solution 1 - Python

As @jonrsharpe noted in a comment, this can be done with typing.Callable:

from typing import Callable

def my_function(func: Callable):

Note: Callable on its own is equivalent to Callable[..., Any]. Such a Callable takes any number and type of arguments (...) and returns a value of any type (Any). If this is too unconstrained, one may also specify the types of the input argument list and return type.

For example, given:

def sum(a: int, b: int) -> int: return a+b

The corresponding annotation is:

Callable[[int, int], int]

That is, the parameters are sub-scripted in the outer subscription with the return type as the second element in the outer subscription. In general:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]

Solution 2 - Python

Another interesting point to note is that you can use the built in function type() to get the type of a built in function and use that. So you could have

def f(my_function: type(abs)) -> int:
    return my_function(100)

Or something of that form

Solution 3 - Python

My specific use case for wanting this functionality was to enable rich code completion in PyCharm. Using Callable didn't cause PyCharm to suggest that the object had a .__code__ attribute, which is what I wanted, in this case.

I stumbled across the types module and..

from types import FunctionType

allowed me to annotate an object with FunctionType and, voilà, PyCharm now suggests my object has a .__code__ attribute.

The OP wasn't clear on why this type hint was useful to them. Callable certainly works for anything that implements .__call__() but for further interface clarification, I submit the types module.

Bummer that Python needed two very similar modules.

Solution 4 - Python

An easiest and fancy solution is:

def f(my_function: type(lambda x: None)):
    return my_function()

This can be proved in the following way:

def poww(num1, num2):
    return num1**num2
    
print(type(lambda x: None) == type(poww))

and the output will be: True

Solution 5 - Python

In python3 it works without import typing:

def my_function(other_function: callable):
    pass

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJonView Question on Stackoverflow
Solution 1 - PythonDimitris Fasarakis HilliardView Answer on Stackoverflow
Solution 2 - PythonHallsville3View Answer on Stackoverflow
Solution 3 - PythonJohn CarrellView Answer on Stackoverflow
Solution 4 - PythonJorge MassihView Answer on Stackoverflow
Solution 5 - PythonJack ScandallView Answer on Stackoverflow