关于python函数/方法调用有什么静态的吗?

Joe*_*Joe 3 python binding cpython dynamic-binding

询问有关反思的问题时,我问:

很好的答案.但说myobject.foo()和之间有区别x = getattr(myobject, "foo"); x();.即使它只是化妆品.在第一个中,foo()是静态编译的.在第二种情况下,字符串可以通过多种方式生成. - 乔1小时前

得到了答案:

呃,马铃薯/马铃薯...在python中,niether是静态编译的,所以它们或多或少相当. - SWeko 1小时前

我知道Python对象的成员存储在字典中,并且一切都是动态的,但我假设给出了以下代码:

class Thing():
  def m(self):
    pass

t = Thing()
Run Code Online (Sandbox Code Playgroud)

生成.pyc时,以下代码会以某种方式静态编译:

t.m()
Run Code Online (Sandbox Code Playgroud)

即编译器知道地址m(),因此在运行时没有点绑定.那个或运行时会缓存后续查找.

虽然这总是涉及到字典:

meth = getattr(t, "m")
meth()
Run Code Online (Sandbox Code Playgroud)

是否所有调用都被视为字典中的字符串查找?或者这两个例子实际上是相同的吗?

Fre*_*Foo 7

它们并不完全相同,但它们都是字典查找,可以用反汇编程序显示dis.dis.

特别是,请注意该LOAD_ATTR指令通过名称动态查找属性.根据文档,它"替换TOS [堆栈顶部] getattr(TOS, co_names[namei])".

>>> from dis import dis
>>> dis(lambda: t.m())
  1           0 LOAD_GLOBAL              0 (t)
              3 LOAD_ATTR                1 (m)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE        
>>> dis(lambda: getattr(t, 'm')())
  1           0 LOAD_GLOBAL              0 (getattr)
              3 LOAD_GLOBAL              1 (t)
              6 LOAD_CONST               0 ('m')
              9 CALL_FUNCTION            2
             12 CALL_FUNCTION            0
             15 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)