Markus M.
Markus M.

Reputation: 23

"from module import class" importing other classes from same module

Given the following files:

a.py
-----
class CommonClass(object):
    def do_thing(self):
        pass

b.py
-----
from a import CommonClass

class SubClassA(CommonClass):
    def do_thing(self):
        print("I am A")

class SubClassB(CommonClass):
    def do_thing(self):
        print("I am B")

c.py
-----
from a import CommonClass
from b import SubClassA

if __name__ == "__main__":
    for member in CommonClass.__subclasses__():
        member().do_thing()

I would expect only SubClassA is imported, and visible when looping through subclasses of CommonClass, but it seems SubClassB is imported as well.

I am running Python 3.8.5 and this is the output of python3 c.py:

$ python3 c.py      
I am A
I am B

How can I only import the classes I want?

Upvotes: 2

Views: 584

Answers (2)

Tomerikoo
Tomerikoo

Reputation: 19414

You did import only SubClassA to c.py. This can be tested by doing

x = SubClassB()

or

x = b.SubClassB()

Both will result in a NameError.

The thing is, that when you import a file, it is actually being ran, even when using from x import y!

This can be easily seen by adding a print("I'm from b.py") at the end of b.py and then running c.py.

This makes both SubClassA and SubClassB be subclasses of CommonClass, which you imported. So, while you don't have access to the SubClassB name, it is still a subclass of CommonClass and you can access it from there.


In general you don't have to import a module to be able to use its objects. Importing expands your namespace to include that module so you can create an object directly. You can still use this module's objects even without importing it if you acquired them in some other way (like importing a third module which returns objects from the second one).


Anyway right now, you are not really using even the imported SubClassA. If you want to "allow" certain classes to be considered only from an external source, you can create an allowed set of classes:

from a import CommonClass
from b import SubClassA

allowed_classes = {SubClassA}

if __name__ == "__main__":
    for member in CommonClass.__subclasses__():
        if member in allowed_classes:
            member().do_thing()

Which only prints I am A

Upvotes: 3

Divyessh
Divyessh

Reputation: 2721

from a import CommonClass
from b import SubClassA

if __name__ == "__main__":

    h = CommonClass.__subclasses__()[0]()
    h.do_thing()

You can do this.

Upvotes: 0

Related Questions