Takahiko Kawasaki
Takahiko Kawasaki

Reputation: 18991

How to adjust the module part of the fully-qualified class name in Python?

The following test shows Python interprets A as dir.a.A. How can I make Python interprets A as dir.A?

$ find * -name "*.py"
dir/a.py
dir/__init__.py
main.py


$ cat dir/a.py
class A():
    pass


$ cat dir/__init__.py
from .a import A


$ cat main.py
from dir import A
print(A)


$ python3 main.py
<class 'dir.a.A'>

I know the following can yield the result I want, but I want to achieve it without changing the directory/file structure.

$ ls
dir.py main.py


$ cat dir.py
class A():
    pass


$ cat main.py
from dir import A
print(A)


$ python3 main.py
<class 'dir.A'>

Or, shouldn't I care about this? (I'm a newbie to Python.)

Upvotes: 0

Views: 246

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121256

First of all: You don't need to do this, and you probably don't want to do this. The standard library is full of examples where what the documentation uses as the import location and the actual module information on the object differ:

>>> from unittest import TestCase
>>> TestCase
<class 'unittest.case.TestCase'>

The full module location is used by tools like pickle (to store only a reference to the class when serialising instances).

You can set the __module__ attribute if you feel you must change it; it is a string that names the full module path:

>>> class A():
...     pass
...
>>> A
<class '__main__.A'>
>>> A.__module__
'__main__'
>>> A.__module__ = 'dir'
>>> A
<class 'dir.A'>

This is the same value as the __name__ attribute on the module. It is available as a global inside a module, in __init__ you could use

from .a import A

A.__module__ = __name__  # rehome here. 

For tools like pickle that's still fine because you actually have a dir.A reference in the dir module.

Upvotes: 1

Related Questions