代码之家  ›  专栏  ›  技术社区  ›  Olivier Melançon iacob

为什么inspect为继承自超类的类返回不同的行?

  •  6
  • Olivier Melançon iacob  · 技术社区  · 6 年前

    在试图弄清楚 a function is called with the @decorator syntax ,我们意识到 inspect 在查看从超类继承的修饰类时,具有不同的行为。

    Windows10下的CPython3.6.2出现以下行为。

    它也在CPython3.7.0的64位Linux下复制。

    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
    

    Foo ['@decorate\n']
    Bar ['class Bar(dict):\n']
    

    为什么遗传会改变人类的行为 检查 ?

    1 回复  |  直到 6 年前
        1
  •  6
  •   user2357112    6 年前

    进一步的实验表明,这是Python行号赋值的一个怪癖。特别是,如果我们使用 dis 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 行):

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

    如果没有基类,则父帧 f_lineno @ 当装潢师运行时。对于基类,父帧位于加载基类行上。