在Python函数定义中->是什么意思?

我最近在看Python 3.3语法规范时注意到一些有趣的事情:

funcdef: 'def' NAME parameters ['->' test] ':' suite

可选的“箭头”块在Python 2中不存在,我在Python 3中找不到任何有关其含义的信息。事实证明这是正确的Python并且它被解释器接受:

def f(x) -> 123:return x

我认为这可能是某种先决条件语法,但是:

  • 我不能在这里测试x,因为它仍然未定义,
  • 无论我在箭头后面放什么(例如2 < 1),它都不会影响函数的行为。

熟悉这种语法风格的人能解释一下吗?

624675 次浏览

这是一个函数注释

更详细地说,Python 2. x有文档字符串,它允许您将元数据字符串附加到各种类型的对象。这非常方便,因此Python 3通过允许您将元数据附加到描述其参数和返回值的函数来扩展该功能。

没有先入为主的用例,但PEP建议了几个。一个非常方便的方法是允许您用预期的类型注释参数;然后很容易编写一个装饰器来验证注释或将参数强制转换为正确的类型。另一个是允许参数特定的留档,而不是将其编码到文档字符串中。

这些是PEP 3107中涵盖的函数注释。具体来说,->标记了返回函数注释。

示例:

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'}

注释是字典,所以你可以这样做:

>>> '{:,} {}'.format(kinetic_energy(12,30),kinetic_energy.__annotations__['return'])'5,400.0 Joules'

你也可以有一个python数据结构,而不仅仅是一个字符串:

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'

或者,您可以使用函数属性来验证调用的值:

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)

打印

>>> f(2,2)AssertionError: x==2; Test: _between: must be between 3 and 10>>> f(3,2.1)AssertionError: y==2.1; Test: <lambda>

正如其他答案所述,->符号用作函数注释的一部分。然而,在最近的Python>= 3.5版本中,它具有定义的含义。

PEP 3107-函数注释描述了规范,定义了语法更改,存储它们的func.__annotations__的存在,以及它的用例仍然开放的事实。

不过,在Python3.5中,PEP 484-类型提示对此赋予了一个单一的含义:->用于指示函数返回的类型。看起来这也将在未来的版本中强制执行,如注释的现有用途呢?所述:

可以想象的最快的方案将在3.6中引入非类型提示注释的无声弃用,在3.7中完全弃用,以及声明类型提示是Python 3.8中唯一允许使用的注释。

(强调我的)

据我所知,这在3.6时还没有真正实现,所以它可能会被撞到未来的版本。

根据这一点,您提供的示例:

def f(x) -> 123:return x

将在未来被禁止(并且在当前版本中将会混淆),它需要更改为:

def f(x) -> int:return x

为了有效地描述函数f返回类型int的对象。

Python本身不会以任何方式使用注释,它几乎填充并忽略它们。由第3方库来使用它们。

def function(arg)->123:

它只是一个返回类型,在这种情况下,整数与你写的数字无关。

喜欢Java

public int function(int args){...}

但是对于Python(吉姆·希利亚德怎么说)返回类型只是一个提示,所以建议返回,但无论如何允许返回其他类型,如字符串。

在以下代码中:

def f(x) -> int:return int(x)

-> int只是告诉f()返回一个整数(但它不会强制函数返回一个整数)。它被称为返回注释,可以作为f.__annotations__['return']访问。

Python还支持参数注释:

def f(x: float) -> int:return int(x)

: float告诉阅读程序(以及一些第三方库/程序,例如pylint)的人x应该是float。它被访问为f.__annotations__['x'],本身没有任何意义。有关更多信息,请参阅留档:

https://docs.python.org/3/reference/compound_stmts.html#function-definitionshttps://www.python.org/dev/peps/pep-3107/

这意味着函数返回的结果类型,但它可以是None

它在面向Python 3. x的现代库中很普遍。

例如,它在库熊猫侧写的代码中有很多地方,例如:

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

我的总结:

  1. 简单地->是为了让开发人员有选择地指定函数的返回类型而引入的。参见Python增强提案3107

  2. 这表明随着Python被广泛采用,未来的事情可能会如何发展-这是强类型的迹象-这是我个人的观察。

  3. 您也可以为参数指定类型。指定函数和参数的返回类型将有助于减少逻辑错误并改进代码增强。

  4. 您可以将表达式作为返回类型(在函数和参数级别),并且可以通过<强>注释对象的'返回'属性访问表达式的结果。<强>注释对于lambda内联函数的表达式/返回值将为空。

def f(x) -> str:return x+4
print(f(45))

将给出结果:49

或者换句话说,'->str'对返回类型没有影响:

print(f(45).__class__)
<class 'int'>

->在python3中引入。

简单来说,->之后的内容表示函数的返回类型。返回类型是可选的。

它只是告诉用户它期望什么或返回值

funcname.__annotations__将打印详细信息

喜欢

def function(name:str ,age:int) -> "printing the personal details ":print(f"name is {name} age is {age}")
function("test",20)print(function.__annotations__)

输出

name is test age is 20{'name': <class 'str'>, 'age': <class 'int'>, 'return': 'printing the personal details '}

即使您返回值,它也不会显示任何内容。

请参考PEP3107规范。这些是函数注释。Python 2. x有文档字符串。类似地,Python 3引入了->作为函数注释的使用。Python在生成留档时使用这些。