为什么inspect返回从超类继承的类的不同行? [英] Why does inspect return different line for class inheriting from superclass?

查看:121
本文介绍了为什么inspect返回从超类继承的类的不同行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图找出是否使用 @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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆