0

Using __name__ inside a method references the module where the class was defined.

Is there a way instead for an object to get the module where it has been instantiated?

4
  • you could use __name__ inside the init of the object to store this exact information for later. Commented Mar 1, 2018 at 10:19
  • 1
    What is your goal with this, what are you trying to accomplish? Commented Mar 1, 2018 at 10:20
  • Python doesn't keep track of where an instance was instantiated. If you need such functionality, you have to implement it yourself (e.g. by passing the module to the constructor). That said, I really can't imagine a reason why anyone would need to do this. Sounds like a code smell to me. Commented Mar 1, 2018 at 10:22
  • It's for this: github.com/andybrice/pypework A library which adds a functional pipeline syntax to Python. So it is quite a dirty metaprogramming hack, pushing what the language is designed to do. I have an object which picks up the identifiers of functions and creates object wrappers for them. At the moment, __name__ is passed to the constructor. But it would be nice if this wasn't necessary. Commented Mar 1, 2018 at 10:30

1 Answer 1

1

So - Python's dynamism allows a function to check the frame object where it was called from. .

It would be better if you could pass the module explicitly to the class constructor, though:

class MyObject:
    def __init__(self, module):
         self.module = module
         ...

And in the other files:

m  = MyObject(__name__)

But, as I mentioned in the first line, you can get to the code calling a module - save if you have an specialized metaclass, the code calling one class's __init__ is where the object is instantiated. So you can write:

import inspect

class MyObject:
    def __init__(self, module):
         caller_frame = inspect.currentframe().f_back
         self.module = caller_frame.f_globals.get("__name__", "<unknown module>")
         ...

The Frame object is an internal Python object that keeps the execution state of a code context while the program is being run. It contain references to globals and locals variables available to that frame, as well as code object, current source line, and so on. The topmost frame (0) is the current frame in execution - the second one to the top (1) is the direct caller of the current function/method. The frame .f_globals attribute is a direct reference to the globals dictionary - the same that would be returned if one would call globals() inside that frame.

Sign up to request clarification or add additional context in comments.

6 Comments

By the way, if you are writing code to try to convey functional stuff into Python, you really should get acquainted with the Frame object. Take a look at github.com/jsbueno/stackfull for more examples.
It's good practice to delete the frame object variable when you're done with it, because otherwise you risk it creating a reference cycle. It'd also be better to avoid sys._getframe, since it's not guaranteed to exist. You can use inspect.currentframe().f_back instead.
All objects in Python can create a "reference cycle" - if you keep references to then. Putting a del to a variable jsut because it references a Frame is no different from deling any other variable: normally a redundant statement. (unless you are dealing with Frame objects inside a generator or async function)
Ahh, that all seems to work. Thank you. I had previously tried to use inspect on frames but clearly was doing something wrong.
There are projects dealign with meta programing that does this in a regular basis. Just include some serious unit testing so that one knows in advance if it works in a particular Python implementation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.