drjrm3
drjrm3

Reputation: 4728

Python modules vs classes

I have the following directory structure:

ican/
  __init__.py
  haz/
    __init__.py
    apple.py
    grape/
      __init.py
      grape.py

where apple.py and grape.py have fruit class definitions. In another test file, I am trying to load a fruit class via something akin to myapple = ican.haz.apple() or mygrape = ican.haz.grape().

What is the correct directory structure and import structure for loading a class of this sort? I have also tried something like import ican.haz as icanhaz and then calling myapple = icanhaz.apple(). I am looking to put all of my classes in the same spot and load them via something like ican.haz.<class>.

Upvotes: 3

Views: 1575

Answers (2)

aneroid
aneroid

Reputation: 16007

To be uniform, either

a) apple.py should be one level lower in an apple folder with an init, or

b) grape.py should be one level higher and not in its own grape folder.

Then your import will be from ican.haz.apple import Apple and from ican.haz.grape import Grape (for option a); or from ican.haz import apple, grape (for option b).

To get the structure you want, go with option b and modify the init under haz.

haz/__init__.py:

from .apple import Apple
from .grape import Grape

__all__ = ['Apple', 'Grape']

And you would import it as import ican.haz.* (considered bad style though). And it is ~mangling the module vs class name~ (not any more since class names corrected). Better to use one of the lines below with option a or b.

Btw, the imports according to your current structure would need to be:

from ican.haz import apple
from ican.haz.grape import Grape

a = apple.Apple()
g = Grape()

Upvotes: 0

TheBlackCat
TheBlackCat

Reputation: 10328

You are confusing two concepts. A python "module" is a file containing python code that can be imported. A python "class" is something that can be defined in a module.

In your example, apple and grape are modules. You cannot calls a module by doing something like apple(), it isn't allowed. You would need to import the class contained in the module.

So say apple.py had a GetApple class defined in it. So apple.py looked like this:

class GetApple(object):
    def __init__(self):
        print("I have an apple!")

Modules can also have functions, so you could have a GetApple function instead:

def GetApple():
    print("I have an apple!")

Modules can also have variables. They can have any number of variables, classes, and functions. You can either import them individually (such as with from apple import GetApple, or import the module and access them from the module import apple. But you cannot import and then call a module (at least not in any reasonable way), only the functions or and classes inside it.

For your directory structure, you could then run it using any of these approaches:

>>> from ican.haz.apple import GetApple
>>> GetApple()
I have an apple!

>>> from ican.haz import apple
>>> apple.GetApple()
I have an apple!

>>> import ican.haz.apple
>>> ican.haz.apple.GetApple()
I have an apple!

And, depending on your __init__.py files, possibly also:

>>> import ican.haz
>>> ican.haz.apple.GetApple()
I have an apple!

>>> import ican
>>> ican.haz.apple.GetApple()
I have an apple!

For grape.py, assuming a corresponding class, this sort of thing would work:

>>> from ican.haz.grape.grape import GetGrape
>>> GetGrape()
I have a grape!

Upvotes: 1

Related Questions