6

type annotation in the function arguments definition: I want to implement a High Order Function in python, and for that I would like to have explicit arguments type. Is there a way to show a 'function' type?

def high_order_math(a: Float, b: Float, func: function):
    return func(a,b)

Here are some findings, appreciate you all that have shared your knowledge

def high_order_math(a: float, b: float, func: Callable[[float, float], float]) -> float:
     return func(a, b)

high_order_math(1,2,3)

Traceback (most recent call last):

File "", line 1, in

File "", line 2, in high_order_math

TypeError: 'int' object is not callable

  • 2
    Are you asking about *type annotation* or runtime type checking? – juanpa.arrivillaga Jun 30 '20 at 18:46
  • Basically it's not really necessary to implement a try except block, since as @Samwise also said. Python interpreter do this checks. This type annotation can be used for both cases. – Samuel Oliveira Jul 02 '20 at 21:19
  • 1
    Who said anything about a try-except block? Again, **what exactly are you asking?** Are you asking how *to write a type annotation for a function*? Or are you asking how to check the type of an object is a function at runtime? – juanpa.arrivillaga Jul 02 '20 at 21:23
  • Don't get me wrong, the question was about type annotation in the function arguments definition. Of course, by the *reading* the question u can see that I know how to write a type annotation, I just didn't know it for cases such as high order functions. Doesn't matter who asked about try-exception, it's just the most basic way to deal with runtime problems for each modern programming language. Look, there are 2 following answers bellow. Both answers can be useful, considering the exact cases you've mentioned. The problem was solved. Have fun! To check types use python built-in `type(func)` – Samuel Oliveira Jul 02 '20 at 22:07

3 Answers3

8

Use the Callable type from typing. The Callable type is a generic so you can specify the signature of the function.

from typing import Callable

def high_order_math(a: float, b: float, func: Callable[[float, float], float]) -> float:
    return func(a, b)
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • 1
    This doesn't actually enforce anything at runtime. – juanpa.arrivillaga Jun 30 '20 at 18:45
  • 1
    The Python interpreter will automatically raise a `TypeError` exception at runtime if you try to invoke `func` and it is not a callable; it's not necessary to do anything special to get that behavior. In the context of a question about typing it's generally understood that what we're interested in is being able to detect the error ahead of time via static analysis aided by type annotations. – Samwise Jun 30 '20 at 20:34
  • The context of the quesiton is *not clear*. That is the point I'm making. In either case, really, this question is a duplicate. But it is unclear what the OP expects, it wouldn't e the first quesiton asked assuming type annotations work like variable declarations that will catch problems at compile time, or even some assume at run time. – juanpa.arrivillaga Jun 30 '20 at 20:44
  • 3
    It was adequately clear to me from OP's use of the phrase "explicit type" and their placeholder attempt at type annotations. If I got it wrong, I trust that OP will ask for clarification. :) – Samwise Jun 30 '20 at 20:48
  • 2
    If that was *adequately clear* then *someone with your experience and rep* should have seen that this was a clear duplicate. [This would generally be the canonical duplicate](https://stackoverflow.com/questions/37835179/how-can-i-specify-the-function-type-in-my-type-hints). Really, either way it is a duplicate. I understand that it's not always obvious, but it's always worth to check these sorts of questions – juanpa.arrivillaga Jul 02 '20 at 21:24
1

You've received a good answer, but inside the function body you can verify is the argument passed is callable:

def high_order_math(a: float, b: float, func):
    if not callable(func):
        raise TypeError
    else:
        print(a + b)
high_order_math(1, 2, lambda x, y: x + y) # works because it's callable
high_order_math(1, 2, 'hello') # raises error because it's not callable
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
0

Try this:

>>> def high_order_math(a, b, func):
...     if callable(func):
...         return func(a, b)
...     raise TypeError(f"{type(func)} is not a function or callable")
... 
>>> high_order_math(3, 4, lambda a,b: a+b)
7
lpozo
  • 598
  • 2
  • 9