我有这个简单的功能:
def f():
print("heh")
当我在现实中调用f时,我正在调用它的调用方法。但是当我在现实中调用f的调用方法时,我调用f的调用方法的调用方法。等等等等。
当调用f()时,python如何运行,它显然必须停在哪里?
我想知道这是否会变得无穷无尽,事实证明,100 000足以让Python崩溃。
>>> exec('f'+100000*'.__call__'+'()')
========= RESTART ==========
这次崩溃的原因是什么?
答案 0 :(得分:1)
对象上的“调用”会导致解释器查找调用它的方法。当通过查找__call__
方法解决该问题时,将调用该方法,然后发生实际情况。 __call__
方法不能仅仅在自身上调用相同的机制。
在函数对象的情况下,我相信有一个内部方法表,首先直接查询是否有一个定义的(C语言)调用处理程序,并且调用它。可能还有__call__
属性执行相同的操作,但我认为引擎会首先检查表(其中一些可能已经在Py 3中重新编写)。
函数的'C'语言调用处理程序是对函数对象和参数包的引用。函数对象包含对代码对象的引用,以及对正确的全局名称空间的引用。代码对象包含对预期参数的描述,以及在python堆栈上实际设置调用所需的所有信息。
当你调用一个类的方法时,有一个小的binder对象有自己的调用方法(包含指向'self'和实际方法'的指针)。
我想主要的一点是某些对象有用Python编码的__call__
方法,但对于许多类型,解释器在查看对象的内部类型描述符后可以直接转到C代码。另一个例子是调用一个类型对象,比如str,它将调用C语言构造函数。