【问题标题】:What does -> mean in Python function definitions?-> 在 Python 函数定义中是什么意思?
【发布时间】:2013-01-01 00:45:48
【问题描述】:

我最近在查看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),都不会影响函数的行为。

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

【问题讨论】:

    标签: python python-3.x annotations function-definition


    【解决方案1】:

    这是function annotation

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

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

    【讨论】:

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

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

    【讨论】:

    • 我认为这是一个完整的例子。
    【解决方案3】:

    在以下代码中:

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

    -&gt; 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/

    【讨论】:

      【解决方案4】:

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

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

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

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

      (强调我的)

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

      据此,您提供的示例:

      def f(x) -> 123:
          return x
      

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

      def f(x) -> int:
          return x
      

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

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

      【讨论】:

      【解决方案5】:

      这表示函数返回的结果类型,但可以是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。"它可以是 None 或任何其他类型。
      【解决方案6】:
      def f(x) -> 123:
          return x
      

      我的总结:

      1. 引入-&gt; 只是为了让开发人员有选择地指定函数的返回类型。见Python Enhancement Proposal 3107

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

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

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

      【讨论】:

        【解决方案7】:

        def function(arg)-&gt;123:

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

        喜欢Java

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

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

        【讨论】:

          【解决方案8】:

          ->是python3中引入的。

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

          【讨论】:

          • 此答案中的指导与之前已发布的答案中的指导有何不同?
          【解决方案9】:
          def f(x) -> str:
          return x+4
          
          print(f(45))
          

          将给出结果:49

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

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

          【讨论】:

            【解决方案10】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多