Why doesnt this give back '12'?
The '+' sign should concatenate two strings, not add them.
def foo(a:str, b:str):
print(a+b)
foo(1,2)
3
That's not what annotations are for. Annotations are metadata, not an instruction to Python to convert data.
From the Function definitions reference documentation:
Parameters may have annotations of the form “
: expression
” following the parameter name. Any parameter may have an annotation even those of the form*identifier
or**identifier
. Functions may have “return” annotation of the form “-> expression
” after the parameter list. These annotations can be any valid Python expression and are evaluated when the function definition is executed. Annotations may be evaluated in a different order than they appear in the source code. The presence of annotations does not change the semantics of a function.
(Bold emphisis mine).
For example, the Python type hinting framework uses annotations to attach type information to functions for static analysis, validating that code actually passes in the types that are expected to be passed in.
Just convert your values explicitly; in the call:
foo(str(1), str(2))
or in the function itself:
def foo(a, b):
print(str(a) + str(b))
or in a decorator:
import functools
import inspect
def typeconversion(f):
"""Converts arguments with a callable attached in the parameter annotation"""
sig = inspect.signature(f)
@functools.wraps(f)
def wrapper(*args, **kwargs):
# convert any argument (including defaults), for which there is a
# callable annotation
bound = sig.bind(*args, **kwargs)
bound.apply_defaults()
args = bound.arguments
for param in sig.parameters.values():
if param.annotation is not param.empty and callable(param.annotation):
args[param.name] = param.annotation(args[param.name])
# call the function with the converted arguments
result = f(*bound.args, **bound.kwargs)
# convert the return value
if sig.return_annotation is not sig.empty and callable(sig.return_annotation):
result = sig.return_annotation(result)
return result
return wrapper
Demo:
>>> @typeconversion
... def foo(a: str, b: str) -> int:
... return a + b
...
>>> foo(42, 101)
42101