Search code examples
pythonpython-3.xclassintrospection

Get variable to which an object is assigned from inside the object?


In Python, I'd like to get the variable to which an object is being assigned to. Something like:

class Parent(object):

    def __init__(self):
        print(???) # Print the variable to which the created instance of 
                   # Parent has been assigned to. 

p = Parent() # This should print 'p'. 

I have come up with this:

import inspect


class Parent(object):

    def __init__(self):
        print((inspect.stack()[-1].code_context[-1].split()[0]))


p = Parent()

which, if I understand correctly, literally looks at the outermost call and there takes the left string part, which happens to be the variable - but to me this looks weird. Is there a better way?


Solution

  • Yes, you can do it, using both inspect and ast to parse the source code which you can find using inspect.stack().

    Note that your solution prints "__main__", for me, and I'm testing on Python 3.5.2, so the answer might be slightly different for other Python versions.

    import inspect
    import ast
    
    class Parent(object):
    
        def __init__(self):
            frame = inspect.stack()[1]
            # Parse python syntax of the assignment line
            st = ast.parse(frame.code_context[0].strip())
            stmt = st.body[0]
            # Assume class being instanced as simple assign statement
            assert(isinstance(stmt, ast.Assign))
            # Parse the target the class is assigned to
            target = stmt.targets[0]
            print(target.id) # prints "p"
    
    p = Parent()
    

    This only works for simple assign statements. If you have a more complex assign statement, say p, n = Parent(), 0, you will need to add more steps to parsing the AST. In principle, all valid statements involving Parent() can be parsed, but in some cases there is no assignment involved (e.g. Parser()).

    The code listed above can therefore only serve as an example how to approach the problem, not as a complete solution.