【问题标题】:What exactly defines a function in Python在 Python 中究竟是什么定义了一个函数
【发布时间】:2018-12-26 09:40:48
【问题描述】:

__dict__ 包含描述对象的属性。但它显示函数对象的空白字典。

我在这里检查了Python: Explain __dict__ attribute,但没有找到具体的答案,尽管thefourthey给出了这个答案。

对于一个类,它里面的变量定义了这个类,但对于一个函数,它不是。那么,究竟是什么定义了功能呢?

 def bar(x):
    return x + 1
 print(bar.__dict__) #{}

 class foo(object):
     def bar(x):
         return x + 1
 print(foo.__dict__)  #['bar': <function foo.bar at 0x058E0420>]

【问题讨论】:

  • 该函数没有任何属性。你期望在那里看到什么?
  • @jonrsharpe,我尝试了多个代码,其中包括变量,但仍然是相同的空白字典。
  • 函数中的变量不是它的属性...

标签: python


【解决方案1】:

函数由其代码对象定义:bar.__code__

如果你检查它(例如通过dir(bar.__code__)),你会看到各种描述函数参数的变量,它是否有任何常量,它的名字是什么,它在哪里定义......最后,它编译的字节码是什么,在bar.__code__.co_code。您可以使用dis 模块查看其可读版本:

import dis
dis.dis(bar)
# =>  2           0 LOAD_FAST                0 (x)
# =>              2 LOAD_CONST               1 (1)
# =>              4 BINARY_ADD
# =>              6 RETURN_VALUE

你可以看到这样的变量名:

bar.__code__.co_varnames
# => ('x',)

您可以在docs for inspect module 中阅读有关代码对象的更多信息。然而,这大部分都是学术性的——绝大多数 Python 程序员永远不需要访问代码对象,甚至不需要了解它。

【讨论】:

    【解决方案2】:

    __dict__ 返回函数的属性——你的函数没有属性。

    函数是一等公民,你也可以给它们添加属性:

    def bar(x):
        bar.call_count += 1  # increment the functions attribute
        return x*x
    
    print(bar.__dict__)
    
    bar.call_count = 0      # add attribute to function - do not call it before this
    print(bar.__dict__)     # you would get an AttributeError trying to access ball_count
    
    bar(4)
    bar(5)
    bar(6)
    print(bar.__dict__)
    

    输出:

    {}
    {'call_count': 0}
    {'call_count': 3}
    

    查看Amadan's答案了解如何获取有关该功能的其他信息。


    除此之外:

    • 通常您不应该使用 __dunder__ 方法 - 如果您认为需要,您很有可能会进入 xy-Problem-Land,可能有更好的方法来实现您想要解决的问题
    • 所有仅在函数内部声明的变量都不会离开它的作用域 - 所以没有太多需要“从外部获取它们” - 您可以在此处阅读有关范围规则的更多信息:Short Description of the Scoping Rules? - 简称是:函数内部声明的内容,保留在函数中。获得它的唯一方法是从函数中 returning 或声明它 global(你应该避免污染你的全局状态)。

    【讨论】:

      猜你喜欢
      • 2010-10-04
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 2023-03-17
      • 2014-08-23
      • 1970-01-01
      • 2016-07-18
      相关资源
      最近更新 更多