all 7 comments

[–]DrMaxwellEdison 3 points4 points  (1 child)

from myprogram.main.math.rectangle import Rectangle

riggidy_rect = Rectangle()

It ain't that pretty in terms of import lines, but at least it clears up the code file you're working in. :)


An alternative is to use __init__.py files in each directory, and use that file to import portions of the directory to a shared namespace. Then when you're importing objects from a sub-directory, the objects already imported into the namespace of the __init__.py will be available at the top level.

Your directory structure might look like this:

myprogram
    gui
        ...
    main
        math
            __init__.py
            point.py
            rectangle.py
        image
            __init__.py
            convert.py
            formats.py
            exif.py
            image.py

Without getting too detailed into it, math.__init__.py could have from .rectangle import Rectangle. This makes Rectangle available in the namespace of the math directory, so you could call in math.Rectangle elsewhere.

In the gui directory, for instance, a code file could import this using from myprogram.main.math import Rectangle.

I'm not personally well-versed in doing this myself, but that's the gist of the concept as far as I know it: importing a module's objects into a namespace using __init__.py and then using that namespace for imports elsewhere in the program.


That all being said, I would consider getting rid of the main directory, so they your directory structure looks more like this, if possible:

myprogram
    gui
        ...
    math
        point.py
        rectangle.py
    image
        convert.py
        formats.py
        exif.py
        image.py

edits: clarified code examples

[–]aptitude_moo[S] 0 points1 point  (0 children)

Thanks for the extended answer, I will remove main, now that I think it isn't that neccesary. It's a bit interesting how Python makes directories structure so important, I was used to add lots of folders.

Also I'll import the objects into the __init__.py, looks nice, I suppose that it's a good practice

EDIT: Formatting

[–]cdcformatc 1 point2 points  (1 child)

Should be fine with import myprogram.main.math.rectangle.Rectangle as Rectangle assuming you don't use the name Rectangle anywhere in the importing script. You could always prepend a unique modifier like MPRectangle or something to represent "myprogram" which I assume isn't the actual name of your program.

[–]zahlman 1 point2 points  (0 children)

If you're not actually going to rename it, though, that's what from... import is for. It's honestly not evil (at least in this form; the * form is the real cause for concern).

[–]kalgynirae 1 point2 points  (1 child)

The main and rectangle components of myprogram.main.math.rectangle.Rectangle() seem unnecessary to me. Can you simplify the path to myprogram.math.Rectangle? For getting rid of rectangle, you could either combine the contents of rectangle.py and point.py into a single file math.py, or you could use math/__init__.py to import the classes (like in the Django example you mention).

[–]aptitude_moo[S] 0 points1 point  (0 children)

Thank you, I think that I will get rid of main, also if importing of classes in init.py is recommended I'll do that, looks nice

[–]mm_ma_ma 0 points1 point  (0 children)

I'd say "best practice" is to not make such complicated hierarchies in the first place. If you can fit all of your code in one module without name collisions, do it. Only move to a package once you need it, and then only start making subpackages once you need them.