Imports and dot-notation

Cameron Simpson cs at cskk.id.au
Wed Aug 9 19:22:41 EDT 2023


On 09Aug2023 12:30, Oliver Schinagl <oliver+python at schinagl.nl> wrote:
>Looking at a python projects code and repository layout, we see the 
>following directory structure.
>
>
>/project/core
>/project/components/module1
>...
>/project/components/moduleN
>/projects/util
>
>(this is far from complete, but enough to help paint a picture.
>
>Some modules import other modules, and I see (at the very least) two 
>(kind of three?) different ways of doing so.
>
>`from project.components.module1 import function1, function2 as func, 
>CONST1, CONST2 as CONST`
>
>or maybe even (which has as an advantage that it becomes clear which 
>namespace something belongs to
>
>`from project.components.module1 import function1, function2 as 
>module1_function2, CONST1, CONST2 as MODULE1_CONST2`
>
>but then it really just becomes personal preference, as the number of 
>characters saved on typing is almost negative (due to having a more 
>complex import).
>
>
>but also the dot notation being used
>
>`from project.components import module1`
>
>where obviously the functions are invoked as `module1.function1` etc
>
>I hope the above is clear enough from an example.
>
>
>Simply put, which of the two would be considered cleaner and more pythonic?

This is almost entirely a programmer preference thing.

The Zen, as usual, offers guideance but not dictates.

As you say, the module1.func form is very clear and has its beauty.  
Personally I lean towards the single name flavour, sometimes with a 
rename. FOr example, with os.path I often go:

     from os.path import join as joinpath

and likewise for several other names from there, because the bare names 
are very generic (eg "join"). I see to be alone here. Many other people 
use:

     import os.path

and use the full os.path.join in their code, which I find jarring and 
visually noisy.

>Now for a bit more thought, looking at PEP8, we notes about imports, 
>but sadly PEP8 does not state which method is better/preferred. While 
>obviously in the end, it's always the maintainers choice in what they 
>prefer, so are tabs vs spaces and PEP8 is opinionated about that too 
>(in a good way, even though I'm not a fan :p).

PEP8 is for the stdlib source code; that said it is also the basis for 
most Python coding styles in the wild.

For me, the Zen's "readability counts" is the most important guideline; 
and to this end, your "module1.function" is an entirely reasonable 
response, particularly if you've got a lot of imports. But it does make 
for more verbose code, and that works against readability to a degree.

This is why it's all subjective.

Particular workplaces may mandate particular styles, but in your 
personal code? Do what seem best, and experience will cause that to 
evolve over time.

Also, the style can depend on the code you're working on. For a small 
module with few imports the:

     from module1 import funcname

can be a win because the code is short, and this short form of funcname 
is both clear and readable. But in a very long piece of code with many 
imports you might go for module1.funcname for clarity, particularly if 
funcname is generic or overlaps with another similar imported name.

Cheers,
Cameron Simpson <cs at cskk.id.au>


More information about the Python-list mailing list