I’m trying to find a way of basically doing a late eval, using context from a different location in the code. As an example, I have a class Friend, and it can be used like this:
>>> class A:
... friend = Friend('B')
...
>>> class B:
... friend = Friend('A')
...
>>> A.friend.getobject()
<class '__main__.B'>
However, Friend is defined elsewhere in the code, in a separate library, and would look something like this:
class Friend:
def __init__(self, objname):
self.objname = objname
def getobject(self):
return eval(self.objname, original_context)
The sqlalchemy ORM has a similar pattern for defining columns, but they implement it by tracking all owning classes (i.e. tables) in a session. I could do something similar if I need to, but I’d like to know if there is another way to do this. I’ve been looking at frames and the interpreter stack, and I think I can get to the relevant frame’s locals using something like inspect.stack()[1][0].f_locals, but I would have to do this in Frame.__init__ which is called before the object is defined.
My questions is how to find original_context, but only at the time it is needed. This comes down to two issues:
1. How to access the environment (or frame?) in which Friend was instantiated.
2. How to access it at the time getobject is called.
You will have to use the fully qualified classname, ie:
And then take that string, extract out the module and import the B class, and generate it like this.
However, in general, a better way is to do:
In this case B isn’t defined at that point, but you can easily do: