Как я могу указать тип функции в моих подсказках типа?

138

Я хочу использовать подсказки типа в моем текущем проекте Python 3.5. Моя функция должна получить функцию как параметр.

Как я могу указать функцию типа в моих подсказках типа?

import typing

def my_function(name:typing.AnyStr, func: typing.Function) -> None:
    # However, typing.Function does not exist.
    # How can I specify the type function for the parameter `func`?

    # do some processing
    pass

Я проверил PEP 483 , но не нашел там подсказки типа функции.

Джон
источник
21
ФункцияCallable
jonrsharpe
3
python.org/dev/peps/pep-0483/#fundamental-building-blocks , последний пункт перед «мы можем добавить».

Ответы:

176

Как отметил @jonrsharpe в комментарии, это можно сделать с помощью typing.Callable:

from typing import AnyStr, Callable

def my_function(name: AnyStr, func: Callable) -> None:

Проблема в том, что Callableона переведена на то, Callable[..., Any]что означает:

Вызываемый объект принимает любое количество аргументов / типа и возвращает значение любого типа. В большинстве случаев это не то, что вам нужно, поскольку вы разрешаете передавать практически любую функцию. Вы хотите, чтобы параметры функции и типы возвращаемых значений также были намеками.

Вот почему многие typesиз typingних были перегружены для поддержки подпрограмм, которые обозначают эти дополнительные типы. Итак, если, например, у вас есть функция, sumкоторая принимает два ints и возвращает int:

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

Ваша аннотация для него будет:

Callable[[int, int], int]

то есть параметры во внешней подписке записываются в подписку с типом возвращаемого значения в качестве второго элемента во внешней подписке. В основном:

Callable[[ParamType1, ParamType2, .., ParamTypeN], ReturnType]
Димитрис Фасаракис Хиллиард
источник
26
этот typingматериал поднимает весь язык Python на ступеньку выше.
javadba
1
@javadba - О, да, но я до сих пор не уверен , на какой циферблат ... Кстати - а что Callable[[Arg, Types, Here], ...]для *args, **kwargs, ключевых слов только арга и позиционных только аргументов? Разве они не думали о соглашении о вызовах в сигнатурах типов для вызываемых объектов? ;)
Томаш Гандор
11

Еще один интересный момент, который следует отметить, заключается в том, что вы можете использовать встроенную функцию, type()чтобы получить тип встроенной функции и использовать его. Так что вы могли бы

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

Или что-то в этом роде

Hallsville3
источник
Подсказки типа могут быть любыми, но они не всегда оценивались лениво. Кроме того, ваша функция действительно принимает только builtin_function_or_methodкак my_function? Не lambdaсработает? Пользовательская функция или связанный метод?
Томаш Гандор
очень умный способ, по крайней мере, для устранения неполадок или мозгового штурма
oldpride