Python中什么定义了一个函数

5

__dict__保存描述对象的属性。但是对于函数对象,它显示为空字典。

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

对于一个类,其中的变量定义了该类,但对于一个函数,不是这样。那么,究竟是什么定义了函数?

 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
@jonrsharpe,我尝试了多个包含变量的代码,但仍然得到相同的空字典。 - Deepak Mishra
函数内的变量不是其属性... - jonrsharpe
2个回答

6
一段代码的功能由其代码对象定义: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',)

你可以在检查模块的文档中了解有关代码对象的更多信息。然而,这大多是学术性的 - 绝大多数Python程序员永远不需要访问代码对象,甚至不需要知道它。


3

__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的回答获取有关该函数的其他信息。


除此之外:

  • 通常情况下,您不应使用__dunder__方法 - 如果您认为需要使用它们,则很可能会陷入xy-Problem-Land,因此最好有更好的方法来解决您要解决的问题
  • 所有仅在函数内部声明的变量都不会离开其作用域 - 因此没有太多必要“从外部获取它们” - 您可以在此处阅读有关作用域规则的更多信息:作用域规则的简短说明? - 简而言之:在函数内部声明的内容将留在函数中。唯一获取它的方法是通过从函数中return它或声明它global(您应避免污染全局状态)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接