I've recently noticed something interesting when looking at Python 3.3 grammar specification:
funcdef: 'def' NAME parameters ['->' test] ':' suite
The optional 'arrow' block was absent in Python 2 and I couldn't find any information regarding its meaning in Python 3. It turns out this is correct Python and it's accepted by the interpreter:
def f(x) -> 123:
return x
I thought that this might be some kind of a precondition syntax, but:
I cannot test x here, as it is still undefined,
No matter what I put after the arrow (e.g. 2 < 1), it doesn't affect the function behavior.
Could anyone familiar with this syntax style explain it?
It's a function annotation.
In more detail, Python 2.x has docstrings, which allow you to attach a metadata string to various types of object. This is amazingly handy, so Python 3 extends the feature by allowing you to attach metadata to functions describing their parameters and return values.
There's no preconceived use case, but the PEP suggests several. One very handy one is to allow you to annotate parameters with their expected types; it would then be easy to write a decorator that verifies the annotations or coerces the arguments to the right type. Another is to allow parameter-specific documentation instead of encoding it into the docstring.
These are function annotations covered in PEP 3107. Specifically, the -> marks the return function annotation.
Examples:
def kinetic_energy(m:'in KG', v:'in M/S')->'Joules':
return 1/2*m*v**2
>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}
Annotations are dictionaries, so you can do this:
>>> '{:,} {}'.format(kinetic_energy(12,30),
kinetic_energy.__annotations__['return'])
'5,400.0 Joules'
You can also have a python data structure rather than just a string:
rd={'type':float,'units':'Joules',
'docstring':'Given mass and velocity returns kinetic energy in Joules'}
def f()->rd:
pass
>>> f.__annotations__['return']['type']
<class 'float'>
>>> f.__annotations__['return']['units']
'Joules'
>>> f.__annotations__['return']['docstring']
'Given mass and velocity returns kinetic energy in Joules'
Or, you can use function attributes to validate called values:
def validate(func, locals):
for var, test in func.__annotations__.items():
value = locals[var]
try:
pr=test.__name__+': '+test.__docstring__
except AttributeError:
pr=test.__name__
msg = '{}=={}; Test: {}'.format(var, value, pr)
assert test(value), msg
def between(lo, hi):
def _between(x):
return lo <= x <= hi
_between.__docstring__='must be between {} and {}'.format(lo,hi)
return _between
def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
validate(f, locals())
print(x,y)
Prints
>>> f(2,2)
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>
In the following code:
def f(x) -> int:
return int(x)
the -> int just tells that f() returns an integer (but it doesn't force the function to return an integer). It is called a return annotation, and can be accessed as f.__annotations__['return'].
Python also supports parameter annotations:
def f(x: float) -> int:
return int(x)
: float tells people who read the program (and some third-party libraries/programs, e. g. pylint) that x should be a float. It is accessed as f.__annotations__['x'], and doesn't have any meaning by itself. See the documentation for more information:
https://docs.python.org/3/reference/compound_stmts.html#function-definitions
https://www.python.org/dev/peps/pep-3107/
As other answers have stated, the -> symbol is used as part of function annotations. In more recent versions of Python >= 3.5, though, it has a defined meaning.
PEP 3107 -- Function Annotations described the specification, defining the grammar changes, the existence of func.__annotations__ in which they are stored and, the fact that it's use case is still open.
In Python 3.5 though, PEP 484 -- Type Hints attaches a single meaning to this: -> is used to indicate the type that the function returns. It also seems like this will be enforced in future versions as described in What about existing uses of annotations:
The fastest conceivable scheme would introduce silent deprecation of non-type-hint annotations in 3.6, full deprecation in 3.7, and declare type hints as the only allowed use of annotations in Python 3.8.
(Emphasis mine)
This hasn't been actually implemented as of 3.6 as far as I can tell so it might get bumped to future versions.
According to this, the example you've supplied:
def f(x) -> 123:
return x
will be forbidden in the future (and in current versions will be confusing), it would need to be changed to:
def f(x) -> int:
return x
for it to effectively describe that function f returns an object of type int.
The annotations are not used in any way by Python itself, it pretty much populates and ignores them. It's up to 3rd party libraries to work with them.
This means the type of result the function returns, but it can be None.
It is widespread in modern libraries oriented on Python 3.x.
For example, it there is in code of library pandas-profiling in many places for example:
def get_description(self) -> dict:
def get_rejected_variables(self, threshold: float = 0.9) -> list:
def to_file(self, output_file: Path or str, silent: bool = True) -> None:
"""Write the report to a file.
def f(x) -> 123:
return x
My summary:
Simply -> is introduced to get developers to optionally specify the return type of the function. See Python Enhancement Proposal 3107
This is an indication of how things may develop in future as Python is adopted extensively - an indication towards strong typing - this is my personal observation.
You can specify types for arguments as well. Specifying return type of the functions and arguments will help in reducing logical errors and improving code enhancements.
You can have expressions as return type (for both at function and parameter level) and the result of the expressions can be accessed via annotations object's 'return' attribute. annotations will be empty for the expression/return value for lambda inline functions.
def function(arg)->123:
It's simply a return type, integer in this case doesn't matter which number you write.
like Java :
public int function(int args){...}
But for Python (how Jim Fasarakis Hilliard said) the return type it's just an hint, so it's suggest the return but allow anyway to return other type like a string..
def f(x) -> str:
return x+4
print(f(45))
Will give the result : 49.
Or in other words '-> str' has NO effect on return type:
print(f(45).__class__)
<class 'int'>
-> is introduced in python3.
In simpler words, the content after the -> denotes the return type of the function.
The return type is optional.
It's just telling the user what it expects or return the value
funcname.__annotations__ will print the details
like
def function(name:str ,age:int) -> "printing the personal details ":
print(f"name is {name} age is {age}")
function("test",20)
print(function.__annotations__)
The Output
name is test age is 20
{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}
even when you return the values it display nothing.
Please refer to the PEP3107 specification. These are function annotations. Python 2.x has docstrings. Similarly, Python 3 introduced the use of -> as function annotations. Python uses these while generating documentation.
Related
I've recently noticed something interesting when looking at Python 3.3 grammar specification:
funcdef: 'def' NAME parameters ['->' test] ':' suite
The optional 'arrow' block was absent in Python 2 and I couldn't find any information regarding its meaning in Python 3. It turns out this is correct Python and it's accepted by the interpreter:
def f(x) -> 123:
return x
I thought that this might be some kind of a precondition syntax, but:
I cannot test x here, as it is still undefined,
No matter what I put after the arrow (e.g. 2 < 1), it doesn't affect the function behavior.
Could anyone familiar with this syntax style explain it?
It's a function annotation.
In more detail, Python 2.x has docstrings, which allow you to attach a metadata string to various types of object. This is amazingly handy, so Python 3 extends the feature by allowing you to attach metadata to functions describing their parameters and return values.
There's no preconceived use case, but the PEP suggests several. One very handy one is to allow you to annotate parameters with their expected types; it would then be easy to write a decorator that verifies the annotations or coerces the arguments to the right type. Another is to allow parameter-specific documentation instead of encoding it into the docstring.
These are function annotations covered in PEP 3107. Specifically, the -> marks the return function annotation.
Examples:
def kinetic_energy(m:'in KG', v:'in M/S')->'Joules':
return 1/2*m*v**2
>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}
Annotations are dictionaries, so you can do this:
>>> '{:,} {}'.format(kinetic_energy(12,30),
kinetic_energy.__annotations__['return'])
'5,400.0 Joules'
You can also have a python data structure rather than just a string:
rd={'type':float,'units':'Joules',
'docstring':'Given mass and velocity returns kinetic energy in Joules'}
def f()->rd:
pass
>>> f.__annotations__['return']['type']
<class 'float'>
>>> f.__annotations__['return']['units']
'Joules'
>>> f.__annotations__['return']['docstring']
'Given mass and velocity returns kinetic energy in Joules'
Or, you can use function attributes to validate called values:
def validate(func, locals):
for var, test in func.__annotations__.items():
value = locals[var]
try:
pr=test.__name__+': '+test.__docstring__
except AttributeError:
pr=test.__name__
msg = '{}=={}; Test: {}'.format(var, value, pr)
assert test(value), msg
def between(lo, hi):
def _between(x):
return lo <= x <= hi
_between.__docstring__='must be between {} and {}'.format(lo,hi)
return _between
def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
validate(f, locals())
print(x,y)
Prints
>>> f(2,2)
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>
In the following code:
def f(x) -> int:
return int(x)
the -> int just tells that f() returns an integer (but it doesn't force the function to return an integer). It is called a return annotation, and can be accessed as f.__annotations__['return'].
Python also supports parameter annotations:
def f(x: float) -> int:
return int(x)
: float tells people who read the program (and some third-party libraries/programs, e. g. pylint) that x should be a float. It is accessed as f.__annotations__['x'], and doesn't have any meaning by itself. See the documentation for more information:
https://docs.python.org/3/reference/compound_stmts.html#function-definitions
https://www.python.org/dev/peps/pep-3107/
As other answers have stated, the -> symbol is used as part of function annotations. In more recent versions of Python >= 3.5, though, it has a defined meaning.
PEP 3107 -- Function Annotations described the specification, defining the grammar changes, the existence of func.__annotations__ in which they are stored and, the fact that it's use case is still open.
In Python 3.5 though, PEP 484 -- Type Hints attaches a single meaning to this: -> is used to indicate the type that the function returns. It also seems like this will be enforced in future versions as described in What about existing uses of annotations:
The fastest conceivable scheme would introduce silent deprecation of non-type-hint annotations in 3.6, full deprecation in 3.7, and declare type hints as the only allowed use of annotations in Python 3.8.
(Emphasis mine)
This hasn't been actually implemented as of 3.6 as far as I can tell so it might get bumped to future versions.
According to this, the example you've supplied:
def f(x) -> 123:
return x
will be forbidden in the future (and in current versions will be confusing), it would need to be changed to:
def f(x) -> int:
return x
for it to effectively describe that function f returns an object of type int.
The annotations are not used in any way by Python itself, it pretty much populates and ignores them. It's up to 3rd party libraries to work with them.
This means the type of result the function returns, but it can be None.
It is widespread in modern libraries oriented on Python 3.x.
For example, it there is in code of library pandas-profiling in many places for example:
def get_description(self) -> dict:
def get_rejected_variables(self, threshold: float = 0.9) -> list:
def to_file(self, output_file: Path or str, silent: bool = True) -> None:
"""Write the report to a file.
def f(x) -> 123:
return x
My summary:
Simply -> is introduced to get developers to optionally specify the return type of the function. See Python Enhancement Proposal 3107
This is an indication of how things may develop in future as Python is adopted extensively - an indication towards strong typing - this is my personal observation.
You can specify types for arguments as well. Specifying return type of the functions and arguments will help in reducing logical errors and improving code enhancements.
You can have expressions as return type (for both at function and parameter level) and the result of the expressions can be accessed via annotations object's 'return' attribute. annotations will be empty for the expression/return value for lambda inline functions.
def function(arg)->123:
It's simply a return type, integer in this case doesn't matter which number you write.
like Java :
public int function(int args){...}
But for Python (how Jim Fasarakis Hilliard said) the return type it's just an hint, so it's suggest the return but allow anyway to return other type like a string..
def f(x) -> str:
return x+4
print(f(45))
Will give the result : 49.
Or in other words '-> str' has NO effect on return type:
print(f(45).__class__)
<class 'int'>
-> is introduced in python3.
In simpler words, the content after the -> denotes the return type of the function.
The return type is optional.
It's just telling the user what it expects or return the value
funcname.__annotations__ will print the details
like
def function(name:str ,age:int) -> "printing the personal details ":
print(f"name is {name} age is {age}")
function("test",20)
print(function.__annotations__)
The Output
name is test age is 20
{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}
even when you return the values it display nothing.
Please refer to the PEP3107 specification. These are function annotations. Python 2.x has docstrings. Similarly, Python 3 introduced the use of -> as function annotations. Python uses these while generating documentation.
I've recently noticed something interesting when looking at Python 3.3 grammar specification:
funcdef: 'def' NAME parameters ['->' test] ':' suite
The optional 'arrow' block was absent in Python 2 and I couldn't find any information regarding its meaning in Python 3. It turns out this is correct Python and it's accepted by the interpreter:
def f(x) -> 123:
return x
I thought that this might be some kind of a precondition syntax, but:
I cannot test x here, as it is still undefined,
No matter what I put after the arrow (e.g. 2 < 1), it doesn't affect the function behavior.
Could anyone familiar with this syntax style explain it?
It's a function annotation.
In more detail, Python 2.x has docstrings, which allow you to attach a metadata string to various types of object. This is amazingly handy, so Python 3 extends the feature by allowing you to attach metadata to functions describing their parameters and return values.
There's no preconceived use case, but the PEP suggests several. One very handy one is to allow you to annotate parameters with their expected types; it would then be easy to write a decorator that verifies the annotations or coerces the arguments to the right type. Another is to allow parameter-specific documentation instead of encoding it into the docstring.
These are function annotations covered in PEP 3107. Specifically, the -> marks the return function annotation.
Examples:
def kinetic_energy(m:'in KG', v:'in M/S')->'Joules':
return 1/2*m*v**2
>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}
Annotations are dictionaries, so you can do this:
>>> '{:,} {}'.format(kinetic_energy(12,30),
kinetic_energy.__annotations__['return'])
'5,400.0 Joules'
You can also have a python data structure rather than just a string:
rd={'type':float,'units':'Joules',
'docstring':'Given mass and velocity returns kinetic energy in Joules'}
def f()->rd:
pass
>>> f.__annotations__['return']['type']
<class 'float'>
>>> f.__annotations__['return']['units']
'Joules'
>>> f.__annotations__['return']['docstring']
'Given mass and velocity returns kinetic energy in Joules'
Or, you can use function attributes to validate called values:
def validate(func, locals):
for var, test in func.__annotations__.items():
value = locals[var]
try:
pr=test.__name__+': '+test.__docstring__
except AttributeError:
pr=test.__name__
msg = '{}=={}; Test: {}'.format(var, value, pr)
assert test(value), msg
def between(lo, hi):
def _between(x):
return lo <= x <= hi
_between.__docstring__='must be between {} and {}'.format(lo,hi)
return _between
def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
validate(f, locals())
print(x,y)
Prints
>>> f(2,2)
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>
In the following code:
def f(x) -> int:
return int(x)
the -> int just tells that f() returns an integer (but it doesn't force the function to return an integer). It is called a return annotation, and can be accessed as f.__annotations__['return'].
Python also supports parameter annotations:
def f(x: float) -> int:
return int(x)
: float tells people who read the program (and some third-party libraries/programs, e. g. pylint) that x should be a float. It is accessed as f.__annotations__['x'], and doesn't have any meaning by itself. See the documentation for more information:
https://docs.python.org/3/reference/compound_stmts.html#function-definitions
https://www.python.org/dev/peps/pep-3107/
As other answers have stated, the -> symbol is used as part of function annotations. In more recent versions of Python >= 3.5, though, it has a defined meaning.
PEP 3107 -- Function Annotations described the specification, defining the grammar changes, the existence of func.__annotations__ in which they are stored and, the fact that it's use case is still open.
In Python 3.5 though, PEP 484 -- Type Hints attaches a single meaning to this: -> is used to indicate the type that the function returns. It also seems like this will be enforced in future versions as described in What about existing uses of annotations:
The fastest conceivable scheme would introduce silent deprecation of non-type-hint annotations in 3.6, full deprecation in 3.7, and declare type hints as the only allowed use of annotations in Python 3.8.
(Emphasis mine)
This hasn't been actually implemented as of 3.6 as far as I can tell so it might get bumped to future versions.
According to this, the example you've supplied:
def f(x) -> 123:
return x
will be forbidden in the future (and in current versions will be confusing), it would need to be changed to:
def f(x) -> int:
return x
for it to effectively describe that function f returns an object of type int.
The annotations are not used in any way by Python itself, it pretty much populates and ignores them. It's up to 3rd party libraries to work with them.
This means the type of result the function returns, but it can be None.
It is widespread in modern libraries oriented on Python 3.x.
For example, it there is in code of library pandas-profiling in many places for example:
def get_description(self) -> dict:
def get_rejected_variables(self, threshold: float = 0.9) -> list:
def to_file(self, output_file: Path or str, silent: bool = True) -> None:
"""Write the report to a file.
def f(x) -> 123:
return x
My summary:
Simply -> is introduced to get developers to optionally specify the return type of the function. See Python Enhancement Proposal 3107
This is an indication of how things may develop in future as Python is adopted extensively - an indication towards strong typing - this is my personal observation.
You can specify types for arguments as well. Specifying return type of the functions and arguments will help in reducing logical errors and improving code enhancements.
You can have expressions as return type (for both at function and parameter level) and the result of the expressions can be accessed via annotations object's 'return' attribute. annotations will be empty for the expression/return value for lambda inline functions.
def function(arg)->123:
It's simply a return type, integer in this case doesn't matter which number you write.
like Java :
public int function(int args){...}
But for Python (how Jim Fasarakis Hilliard said) the return type it's just an hint, so it's suggest the return but allow anyway to return other type like a string..
def f(x) -> str:
return x+4
print(f(45))
Will give the result : 49.
Or in other words '-> str' has NO effect on return type:
print(f(45).__class__)
<class 'int'>
-> is introduced in python3.
In simpler words, the content after the -> denotes the return type of the function.
The return type is optional.
It's just telling the user what it expects or return the value
funcname.__annotations__ will print the details
like
def function(name:str ,age:int) -> "printing the personal details ":
print(f"name is {name} age is {age}")
function("test",20)
print(function.__annotations__)
The Output
name is test age is 20
{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}
even when you return the values it display nothing.
Please refer to the PEP3107 specification. These are function annotations. Python 2.x has docstrings. Similarly, Python 3 introduced the use of -> as function annotations. Python uses these while generating documentation.
I'm using Python PEP484 type hints to write a type-checker for a DSL I've written in Python. If I have a function expecting type T for one of its arguments, and it's being called with an expression of type S, how can I check whether the call is valid? Is using issubclass(S, T) enough? If so, why does mypy have such a complicated is_subtype check? Or should I just use the mypy version?
Edit: Here's an example to clarify what I mean. The DSL has a function defined as:
T = TypeVar('T', float, str)
def op_add(operand1: T, operand2: T) -> T:
"Number addition or string concatenation."
# In this DSL, `+` cannot be used with lists
return operand1 + operand2 # Rely on Python overloading of `+`
Then a user types in an expression which is parsed into a syntax tree, with a branch that could be: node = OperatorNode('+', Literal([5.0]), Variable("abc")). We don't know the value of the abc variable yet, but lists can never be used with +, so I want to raise a TypeError to alert the user.
If I do issubclass(typing.List[float], var), that gives me False, so I can raise an error right away. My question is whether this check is guaranteed to work across cases as I build out the DSL, or if I need to use a more complex check like mypy
issubclass check is sufficient if neither argument to issubclass includes constructs from typing module such as Union, Callable, Any, generics, etc.
typing constructs exist in python runtime as a shadow of their true form, that is they don't support many of the operations that make sense conceptually:
issubclass(List[int], List[int]) # runtimem error
issubclass(List[int], List) # True (as expected)
issubclass(str, Union[str]) # runtime error
issubclass(Union[str], str) # True (as expected)
issubclass(Union[int, str], str) # runtime error
Sometimes issubclass will work with typing constructs, but in general, it may raise an exception or give an incorrect answer; you'll need to figure out what to do on a case by case basis.
mypy has a more complicated is_subtype because it does need to handle all the typing constructs, and even then there is still some work to be done there.
I've recently noticed something interesting when looking at Python 3.3 grammar specification:
funcdef: 'def' NAME parameters ['->' test] ':' suite
The optional 'arrow' block was absent in Python 2 and I couldn't find any information regarding its meaning in Python 3. It turns out this is correct Python and it's accepted by the interpreter:
def f(x) -> 123:
return x
I thought that this might be some kind of a precondition syntax, but:
I cannot test x here, as it is still undefined,
No matter what I put after the arrow (e.g. 2 < 1), it doesn't affect the function behavior.
Could anyone familiar with this syntax style explain it?
It's a function annotation.
In more detail, Python 2.x has docstrings, which allow you to attach a metadata string to various types of object. This is amazingly handy, so Python 3 extends the feature by allowing you to attach metadata to functions describing their parameters and return values.
There's no preconceived use case, but the PEP suggests several. One very handy one is to allow you to annotate parameters with their expected types; it would then be easy to write a decorator that verifies the annotations or coerces the arguments to the right type. Another is to allow parameter-specific documentation instead of encoding it into the docstring.
These are function annotations covered in PEP 3107. Specifically, the -> marks the return function annotation.
Examples:
def kinetic_energy(m:'in KG', v:'in M/S')->'Joules':
return 1/2*m*v**2
>>> kinetic_energy.__annotations__
{'return': 'Joules', 'v': 'in M/S', 'm': 'in KG'}
Annotations are dictionaries, so you can do this:
>>> '{:,} {}'.format(kinetic_energy(12,30),
kinetic_energy.__annotations__['return'])
'5,400.0 Joules'
You can also have a python data structure rather than just a string:
rd={'type':float,'units':'Joules',
'docstring':'Given mass and velocity returns kinetic energy in Joules'}
def f()->rd:
pass
>>> f.__annotations__['return']['type']
<class 'float'>
>>> f.__annotations__['return']['units']
'Joules'
>>> f.__annotations__['return']['docstring']
'Given mass and velocity returns kinetic energy in Joules'
Or, you can use function attributes to validate called values:
def validate(func, locals):
for var, test in func.__annotations__.items():
value = locals[var]
try:
pr=test.__name__+': '+test.__docstring__
except AttributeError:
pr=test.__name__
msg = '{}=={}; Test: {}'.format(var, value, pr)
assert test(value), msg
def between(lo, hi):
def _between(x):
return lo <= x <= hi
_between.__docstring__='must be between {} and {}'.format(lo,hi)
return _between
def f(x: between(3,10), y:lambda _y: isinstance(_y,int)):
validate(f, locals())
print(x,y)
Prints
>>> f(2,2)
AssertionError: x==2; Test: _between: must be between 3 and 10
>>> f(3,2.1)
AssertionError: y==2.1; Test: <lambda>
In the following code:
def f(x) -> int:
return int(x)
the -> int just tells that f() returns an integer (but it doesn't force the function to return an integer). It is called a return annotation, and can be accessed as f.__annotations__['return'].
Python also supports parameter annotations:
def f(x: float) -> int:
return int(x)
: float tells people who read the program (and some third-party libraries/programs, e. g. pylint) that x should be a float. It is accessed as f.__annotations__['x'], and doesn't have any meaning by itself. See the documentation for more information:
https://docs.python.org/3/reference/compound_stmts.html#function-definitions
https://www.python.org/dev/peps/pep-3107/
As other answers have stated, the -> symbol is used as part of function annotations. In more recent versions of Python >= 3.5, though, it has a defined meaning.
PEP 3107 -- Function Annotations described the specification, defining the grammar changes, the existence of func.__annotations__ in which they are stored and, the fact that it's use case is still open.
In Python 3.5 though, PEP 484 -- Type Hints attaches a single meaning to this: -> is used to indicate the type that the function returns. It also seems like this will be enforced in future versions as described in What about existing uses of annotations:
The fastest conceivable scheme would introduce silent deprecation of non-type-hint annotations in 3.6, full deprecation in 3.7, and declare type hints as the only allowed use of annotations in Python 3.8.
(Emphasis mine)
This hasn't been actually implemented as of 3.6 as far as I can tell so it might get bumped to future versions.
According to this, the example you've supplied:
def f(x) -> 123:
return x
will be forbidden in the future (and in current versions will be confusing), it would need to be changed to:
def f(x) -> int:
return x
for it to effectively describe that function f returns an object of type int.
The annotations are not used in any way by Python itself, it pretty much populates and ignores them. It's up to 3rd party libraries to work with them.
This means the type of result the function returns, but it can be None.
It is widespread in modern libraries oriented on Python 3.x.
For example, it there is in code of library pandas-profiling in many places for example:
def get_description(self) -> dict:
def get_rejected_variables(self, threshold: float = 0.9) -> list:
def to_file(self, output_file: Path or str, silent: bool = True) -> None:
"""Write the report to a file.
def f(x) -> 123:
return x
My summary:
Simply -> is introduced to get developers to optionally specify the return type of the function. See Python Enhancement Proposal 3107
This is an indication of how things may develop in future as Python is adopted extensively - an indication towards strong typing - this is my personal observation.
You can specify types for arguments as well. Specifying return type of the functions and arguments will help in reducing logical errors and improving code enhancements.
You can have expressions as return type (for both at function and parameter level) and the result of the expressions can be accessed via annotations object's 'return' attribute. annotations will be empty for the expression/return value for lambda inline functions.
def function(arg)->123:
It's simply a return type, integer in this case doesn't matter which number you write.
like Java :
public int function(int args){...}
But for Python (how Jim Fasarakis Hilliard said) the return type it's just an hint, so it's suggest the return but allow anyway to return other type like a string..
def f(x) -> str:
return x+4
print(f(45))
Will give the result : 49.
Or in other words '-> str' has NO effect on return type:
print(f(45).__class__)
<class 'int'>
-> is introduced in python3.
In simpler words, the content after the -> denotes the return type of the function.
The return type is optional.
It's just telling the user what it expects or return the value
funcname.__annotations__ will print the details
like
def function(name:str ,age:int) -> "printing the personal details ":
print(f"name is {name} age is {age}")
function("test",20)
print(function.__annotations__)
The Output
name is test age is 20
{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}
even when you return the values it display nothing.
Please refer to the PEP3107 specification. These are function annotations. Python 2.x has docstrings. Similarly, Python 3 introduced the use of -> as function annotations. Python uses these while generating documentation.
One of the new features in python3.5 is type hinting. For example the code below is valid now:
def greeting(name: str) -> str:
return 'Hello ' + name
But, as I understand, it doesn't check anything by itself and also is interpreted absolutely the same way as this:
def greeting(name):
return 'Hello ' + name
and was implemented mostly to help static analyzers (and to make code that is easier to understand). But is there (or is planned to be implemented in the future) any way (maybe by using some third-party libraries) to make python throw errors when an argument of an invalid type is passed to a function with annotated argument types (using only type-hinting syntax)?
Type hints implement PEP 0484 which explicitly lists as a non-goal:
While the proposed typing module will contain some building blocks for
runtime type checking -- in particular the get_type_hints() function
-- third party packages would have to be developed to implement specific runtime type checking functionality, for example using
decorators or metaclasses. Using type hints for performance
optimizations is left as an exercise for the reader.
From this it seems to follow that the Python developers have no plan to add the functionality that you seek. The quote mentions decorators and that does seem the way to go. In concept it seems straightforward -- the decorator would use get_type_hints() on the function to be decorated and would iterate through the arguments, checking their types against any hints, either throwing an error if there is a clash or simply passing on the arguments to the function. This would be similar to pzelasko's answer but with the decorator using the hints to automatically handle the boiler-plate code. The simplest approach would be to simply vet the arguments, though you should also be able to make a decorator which would raise an error if the return type clashes with the hint. I don't yet have Python 3.5 and don't have the time to pursue it -- but it seems like a good learning exercise for someone who wants to learn about both decorators and type hints. Perhaps you can be one of the "third parties" the PEP alludes to.
If you use Python3.6 annotations, you can use typeguard decorators:
https://typeguard.readthedocs.io/en/latest/userguide.html#using-the-decorator
NB: This should only be a "debug" or "testing" tool, not a production one.
Thus, they advise to add the -O option to python to run without in production.
It does not check inline variable annotation checks automatically, only function parameters, function return and object types.
From the doc:
from typeguard import typechecked
#typechecked
def some_function(a: int, b: float, c: str, *args: str) -> bool:
...
return retval
#typechecked
class SomeClass:
# All type annotated methods (including static and class methods and properties)
# are type checked.
# Does not apply to inner classes!
def method(x: int) -> int:
...
You may also automate this to all the functions with:
with install_import_hook('myapp'):
from myapp import some_module
I think the simplest way is to check the type:
def greeting(name):
if not isinstance(name, str):
raise TypeError('Expected str; got %s' % type(name).__name__)
return 'Hello ' + name
Since the release of python 3.7, it has been possible to do this using functools.singledispatch.
from functools import singledispatch
#singledispatch
def greet(arg: object):
raise NotImplementedError(f"Don't know how to greet {type(arg)}")
#greet.register
def _(arg: str):
print(f"Hello, {arg}!")
#greet.register
def _(arg: int):
print(', '.join("Hello" for _ in range(arg)), "!")
greet("Bob") # string implementation is called — prints "Hello, Bob!"
greet(4) # int implementation is called — prints "Hello, Hello, Hello, Hello!"
greet(["Alice, Bob"]) # no list implementation, so falls back to the base implementation — will raise an exception
In the above example, a base implementation is registered that will raise NotImplementedError. This is the "fallback" implementation that is returned if none of the other implementations is suitable.
Following the definition of the base implementation, an arbitrary number of type-specific implementations can be registered, as shown in the example — the function behaves completely differently depending on the type of the argument that is fed to it, and the #singledispatch method uses type annotations to register a certain implementation of a function with a certain type.
A singledispatch function can have any number of arguments, but only the type annotation for the first argument is relevant to which implementation is called.
One can use the library https://github.com/h2oai/typesentry for doing this on runtime.