ChatGPT解决这个技术问题 Extra ChatGPT

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

我最近在查看 Python 3.3 grammar specification 时注意到一些有趣的事情:

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

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

def f(x) -> 123:
    return x

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

我不能在这里测试 x,因为它仍然是未定义的,

无论我在箭头后面放什么(例如 2 < 1),它都不会影响函数的行为。

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


K
Katriel

这是一个function annotation

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

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


该信息可用作 .__annotations__ 属性。
哇,我错过了相当广泛的知识领域——不仅是返回值注释,还有参数注释。非常感谢 :)。
@Krotton 不能怪你错过它,它实际上没有使用。我只遇到过一个使用它们的库,而且非常晦涩。
__annotations__ 属性是一个字典。键 return 是用于检索箭头后面的值的键。
@delnan - 可能它大部分未被使用的原因是因为大多数 python 库仍然旨在与 python2.x 兼容。随着 python3.x 开始变得更加标准,我们可能会看到更多这样的东西出现在这里和那里......
d
dawg

这些是 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>

我认为这是一个完整的例子。
这非常有用,谢谢!虽然,我记得下划线 _ 允许您调用最后一个函数/变量,但我想知道在这种情况下 lambda 作为 _y 做什么?另外,可以只用 _ 替换 _between 吗?
在这两种情况下,_ 都是 的快捷方式,我的意思是与 [that] 的名称相同,但我不想弄清楚命名空间是否允许我使用相同的名称,否则会造成混淆。 使用 between 和内部函数 _between 如果名称相同,则不需要但会混淆。这些可能是相同的名称。使用 lambda,您可以获得 lambda 函数的名称(dict 的键)和参数的名称。同样,如果名称相同,则相似但令人困惑。
M
Maximouse

在以下代码中:

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-definitions https://www.python.org/dev/peps/pep-3107/


D
Dimitris Fasarakis Hilliard

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

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

但是,在 Python 3.5 中,PEP 484 -- Type Hints 对此附加了一个含义:-> 用于指示函数返回的类型。如 What about existing uses of annotations 中所述,这似乎也将在未来的版本中强制执行:

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

(强调我的)

据我所知,截至 3.6 尚未实际实施,因此它可能会与未来版本发生冲突。

据此,您提供的示例:

def f(x) -> 123:
    return x

将来会被禁止(并且在当前版本中会令人困惑),它需要更改为:

def f(x) -> int:
    return x

以便它有效地描述函数 f 返回一个类型为 int 的对象。

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


不错的答案。只是出于好奇,您是否在代码中使用它们?
V
Vitalii

这表示函数返回的结果类型,但它可以是 None

它广泛存在于面向 Python 3.x 的现代库中。

例如,它在很多地方都有库 pandas-profiling 的代码,例如:

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.

“这意味着函数返回的结果类型,但它可以是无。”它可以是 None 或任何其他类型。
T
TheTechRobo Stands for Ukraine
def f(x) -> 123:
    return x

我的总结:

引入了 Simply -> 让开发人员可以选择指定函数的返回类型。请参阅 Python Enhancement Proposal 3107 这表明随着 Python 被广泛采用,未来可能会如何发展——表明强类型化——这是我个人的观察。您也可以指定参数的类型。指定函数和参数的返回类型将有助于减少逻辑错误和改进代码增强。您可以将表达式作为返回类型(在函数和参数级别),并且可以通过注释对象的“返回”属性访问表达式的结果。对于 lambda 内联函数的表达式/返回值,注释将为空。


M
Mike D3ViD Tyson

def function(arg)->123:

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

像 Java :

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

但是对于 Python(Jim Fasarakis Hilliard 怎么说)返回类型只是一个提示,所以它建议返回,但无论如何都允许返回其他类型,如字符串..


M
Mate Mrše
def f(x) -> str:
return x+4

print(f(45))

将给出结果:49。

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

print(f(45).__class__)

<class 'int'>

v
vignesh

-> 在python3中引入。

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


此答案中的指导与已发布的先前答案中的指导有何不同?
返回类型可能仍然不同,注解就像一个解释函数返回值的表达式,但是如果我们把 str 放在 '->' 之后但我们返回一个 int,python 不会给出任何错误。
K
Krunal Akbari

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

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

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