Why does inspect return different line for class inheriting from superclass?

2024/4/15 2:18:50

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.

The following behaviour was found with CPython 3.6.2 under Windows 10.

It was also reproduced in CPython 3.7.0 under Linux 64 bits.

import inspectdef decorate(f):lines = inspect.stack()[1].code_contextprint(f.__name__, lines)return f@decorate
class Foo:pass@decorate
class Bar(dict):pass


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

Why does inheritance change the behaviour of inspect?


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 sysdis.dis(sys._getframe().f_code)def dec(): pass@dec
class Foo: pass@dec
class Bar(Foo): pass

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_CLASS62 LOAD_CONST               4 (<code object Foo at 0x2b2a65422810, file "./prog.py", line 8>)65 LOAD_CONST               5 ('Foo')68 MAKE_FUNCTION            071 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)

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_CLASS87 LOAD_CONST               6 (<code object Bar at 0x2b2a654a0f60, file "./prog.py", line 11>)90 LOAD_CONST               7 ('Bar')93 MAKE_FUNCTION            096 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)

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.


Related Q&A

Sorting a list of tuples with multiple conditions

I am currently trying to sort the following list:list_ = [(1, 0101), (1, 1010), (1, 101), (2, 01), (2, 010), (2, 10)]These are the steps I want to take in order to sort it:Sort the list by the value of…

Tensorboard error: Tensor object has no attribute value

My goal: Add arbitrary text to tensorboard.My code:text = "muh teeeext" summary = tf.summary.text("Muh taaaag", tf.convert_to_tensor(text)) writer.add_summary(summary)My error:File …

How to embed Google Speech to Text API in Python program? [closed]

Closed. This question is seeking recommendations for books, tools, software libraries, and more. It does not meet Stack Overflow guidelines. It is not currently accepting answers.We don’t allow questi…

shell script remote execution using python

Is there a way that I can use Python on Windows to execute shell scripts which are located on a remote Unix machine?P.S: Sorry about the late edit. I do know of Paramiko, but I wanted to know if there…

Shutdown for socketserver based Python 3 server hangs

I am working on a "simple" server using a threaded SocketServer in Python 3.I am going through a lot of trouble implementing shutdown for this. The code below I found on the internet and shut…

How do I url encode in Python?

I tried this: but it doesnt work.print urllib.urlencode("http://"+SITE_DOMAIN+"/go/")I want to turn it into a string with url encodings

resampling pandas series with numeric index

suppose I have a pandas.Series with index with numeric value type e.g. pd.Series( [10,20], [1.1, 2.3] )How do we resample above series with 0.1 interval? look like the .resample func only work on date…

Python3 Tkinter popup menu not closing automatically when clicking elsewhere

Im running Python 3.3.3 (and right now Im on Ubuntu but I also develop on Mac and Windows, which I havent yet tested). I have a Treeview object that responds to right click on items and shows a context…

How does python process a signal?

What is the workflow of processing a signal in python ? I set a signal handler, when the signal occur ,how does python invoke my function? Does the OS invoke it just like C program? If I am in a C e…

Pandas Dataframe to dict grouping by column

I have a dataframe like this:Subject_id Subject Score Subject_1 Math 5 Subject_1 Language 4 Subject_1 Music 8 Subject_2 …