为什么inspect返回从超类继承的类的不同行? [英] Why does inspect return different line for class inheriting from superclass?
问题描述
试图找出是否使用 @decorator
调用函数时,语法,我们意识到在查看从超类继承的装饰类时,检查
具有不同的行为。
While trying to figure out if a function is called with the @decorator
syntax, we realized that inspect
has a different behaviour when looking at a decorated class that inherits from a superclass.
在Windows 10下使用CPython 3.6.2发现以下行为。
The following behaviour was found with CPython 3.6.2 under Windows 10.
在Linux 64位下的CPython 3.7.0中也再现了该行为。
It was also reproduced in CPython 3.7.0 under Linux 64 bits.
import inspect
def decorate(f):
lines = inspect.stack()[1].code_context
print(f.__name__, lines)
return f
@decorate
class Foo:
pass
@decorate
class Bar(dict):
pass
输出
Output
Foo ['@decorate\n']
Bar ['class Bar(dict):\n']
为什么继承会改变检查的行为
?
推荐答案
进一步的实验表明,这是Python行号分配的一个怪癖。特别是,如果我们使用 dis
来查看带有和不带有基本类:
Further experiment shows that this is a quirk of Python's line number assignment. Particularly, if we use dis
to see the disassembly of code with and without a base class:
import dis
import sys
dis.dis(sys._getframe().f_code)
def dec(): pass
@dec
class Foo: pass
@dec
class Bar(Foo): pass
我们看到 Foo
,其中涉及的指令的行号为8(与 @dec
行相对应):
We see that for Foo
, the instructions involved have line number 8 (corresponding to the @dec
line):
8 58 LOAD_NAME 4 (dec)
61 LOAD_BUILD_CLASS
62 LOAD_CONST 4 (<code object Foo at 0x2b2a65422810, file "./prog.py", line 8>)
65 LOAD_CONST 5 ('Foo')
68 MAKE_FUNCTION 0
71 LOAD_CONST 5 ('Foo')
74 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
77 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
80 STORE_NAME 5 (Foo)
但是对于 Bar
,对于加载基类的 LOAD_NAME
,行号从11升至12。 >
But for Bar
, the line number advances from 11 to 12 for the LOAD_NAME
that loads the base class:
11 83 LOAD_NAME 4 (dec)
86 LOAD_BUILD_CLASS
87 LOAD_CONST 6 (<code object Bar at 0x2b2a654a0f60, file "./prog.py", line 11>)
90 LOAD_CONST 7 ('Bar')
93 MAKE_FUNCTION 0
96 LOAD_CONST 7 ('Bar')
12 99 LOAD_NAME 5 (Foo)
102 CALL_FUNCTION 3 (3 positional, 0 keyword pair)
105 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
108 STORE_NAME 6 (Bar)
无基本分类s,装饰器运行时,父框架的 f_lineno
在 @
行上。对于基类,父框架位于加载基类行上。
With no base class, the parent frame's f_lineno
is on the @
line when the decorator runs. With a base class, the parent frame is on the load-the-base-class line.
这篇关于为什么inspect返回从超类继承的类的不同行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!