Python: can a decorator determine if a function is being defined inside a class?

前端 未结 6 868
Happy的楠姐
Happy的楠姐 2021-02-07 11:58

I\'m writing a decorator, and for various annoying reasons[0] it would be expedient to check if the function it is wrapping is being defined stand-alone or as part of a class (a

6条回答
  •  没有蜡笔的小新
    2021-02-07 12:36

    Take a look at the output of inspect.stack() when you wrap a method. When your decorator's execution is underway, the current stack frame is the function call to your decorator; the next stack frame down is the @ wrapping action that is being applied to the new method; and the third frame will be the class definition itself, which merits a separate stack frame because the class definition is its own namespace (that is wrapped up to create a class when it is done executing).

    I suggest, therefore:

    defined_in_class = (len(frames) > 2 and
                        frames[2][4][0].strip().startswith('class '))
    

    If all of those crazy indexes look unmaintainable, then you can be more explicit by taking the frame apart piece by piece, like this:

    import inspect
    frames = inspect.stack()
    defined_in_class = False
    if len(frames) > 2:
        maybe_class_frame = frames[2]
        statement_list = maybe_class_frame[4]
        first_statment = statement_list[0]
        if first_statment.strip().startswith('class '):
            defined_in_class = True
    

    Note that I do not see any way to ask Python about the class name or inheritance hierarchy at the moment your wrapper runs; that point is "too early" in the processing steps, since the class creation is not yet finished. Either parse the line that begins with class yourself and then look in that frame's globals to find the superclass, or else poke around the frames[1] code object to see what you can learn — it appears that the class name winds up being frames[1][0].f_code.co_name in the above code, but I cannot find any way to learn what superclasses will be attached when the class creation finishes up.

提交回复
热议问题