什么在Python中精确定义了一个函数

时间:2018-12-26 09:40:49

标签: python

__dict__保存描述对象的属性。但是它显示了功能对象的空白字典。

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

对于一个类,其内部的变量定义该类,但对于一个函数,则不是。那么,到底什么定义了功能?

 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>]

2 个答案:

答案 0 :(得分: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',)

您可以在docs for inspect module中了解有关代码对象的更多信息。但是,大多数情况是学术上的-绝大多数Python程序员永远都不需要访问代码对象,甚至也不需要了解它。

答案 1 :(得分: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's答案。


除此之外:

  • 通常,您不应该使用__dunder__方法-如果您认为有必要,很可能会使用xy-Problem-Land,这可能是实现您要解决的问题的更好的方法
  • 仅在函数内部声明的所有变量都不会超出范围-因此没有太多“从外部获取它们”的要求-您可以在此处详细了解范围规则:Short Description of the Scoping Rules?-简短它的作用是:在函数内部声明的内容,保留在函数中。获得它的唯一方法是从函数中return对其进行声明或将其声明为global(应避免污染全局状态)。