Get the source of a class reliably?!?

dieter dieter at
Tue Apr 30 02:38:55 EDT 2019

"computermaster360 ." <computermaster360 at> writes:

> Does anyone have an idea why classes don't contain their definition
> line number as functions or methods do?
>>>> some_fun.__code__.co_firstlineno
> 123

Because classes do not have associated "code" objects.

As you see above, it is not the function itself ("some_fun" in
your case) that carries the line information but the associated
"code object" ("some_fun.__code__").

Functions typically are executed several times and
each execution needs to execute the associated code;
therefore, functions reference this code.
There is no specific code directly associated with a class: 
general (i.e. not class specific) code is used to collect
the operands for the class contruction (i.e. base classes, attribute/method
definitions), then the class' metaclass is used to really construct
the class object. Therefore, class objects have no associated "code object".

> ...
> This leads to some funny stuff when using `inspect`, such as this:
> -- -----------------------------
> """
> class C:
> """
> class C:
>   "this is a perfectly ok class"
> ...
>>>> inspect.getsource(weird.C)
> class C:
> Why ???

In order to answer questions of this kind yourself, you
can use the fact that Python is open source.

A look into "" shows that Python uses the following
code to find the source lines for a class:

    if isclass(object):
        name = object.__name__
        pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
        # make some effort to find the best matching class definition:
        # use the one with the least indentation, which is the one
        # that's most probably not inside a function definition.
        candidates = []
        for i in range(len(lines)):
            match = pat.match(lines[i])
            if match:
                # if it's at toplevel, it's already the best one
                if lines[i][0] == 'c':
                    return lines, i
                # else add whitespace to candidate list
                candidates.append((, i))
        if candidates:
            # this will sort by whitespace, and by line number,
            # less whitespace first
            return lines, candidates[0][1]

The comment "make some effort ..." indicates that the author
knew that the result will not be correct in all cases.
You have found such a case.

More information about the Python-list mailing list