473,396 Members | 1,966 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Good practice when writing modules...

r0g
I'm collecting together a bunch of fairly random useful functions I have
written over the years into a module. Generally speaking is it best to

a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...

b) Include them in each function individually.

Stylistically I like the idea of b) better as it makes for easy
refactoring in the future but is there any drawback to doing it this
way? i.e. does it get repeatedly parsed, use more memory, become
inefficient when several functions that use the same includes are
invoked etc Or does it really not matter?

Performance is probably not important for the majority of these
functions but there's the odd one that may end up in an inner loop some day.

Cheers,

Roger.
Nov 15 '08 #1
11 1893
r0g <ai******@technicalbloke.comwrites:
I'm collecting together a bunch of fairly random useful functions I have
written over the years into a module. Generally speaking is it best to

a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...

b) Include them in each function individually.

Stylistically I like the idea of b) better as it makes for easy
refactoring in the future but is there any drawback to doing it this
way? i.e. does it get repeatedly parsed, use more memory, become
inefficient when several functions that use the same includes are
invoked etc Or does it really not matter?
I guess it costs you a dictionary lookup (in sys.modules) and an
assignment every time the import statement is executed. But the module
is not reimported every time.
Performance is probably not important for the majority of these
functions but there's the odd one that may end up in an inner loop some day.
It depends on the function but unless it is a function with special
status (such as testing, or a main() function) I would import stuff at
the top of the module. I makes it clear what the module depends on.

--
Arnaud
Nov 15 '08 #2
r0g:
a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...
b) Include them in each function individually.
This is a interesting topic, that requires some care.
Generally I suggest you put them at the top, so they can be found and
seen with less problems (*), it's the standard.
If a function is called only once in a while (like a plotting
function), and to import its module(s) it needs lot of time and memory
(like matplotlib), then you may move the import inside the function
itself, especially if such function isn't speed-critical.
(*)
I generally agree with the PEP8 but regarding this I don't follow it:
I feel free to put more than one of them on the same line:
import os, sys, ...
I generally list the built-in modules first, then the well known one
(pyparsing, numpy, etc), and then my ones or less known ones.

I also put a comment after each import, with the name of the function/
class it is used into:

import foo # used by baz()
import bar # used by spam()

....
def baz(n):
return foo(n) * 10
....
def spam(k):
return bar(k) - 20

Time ago I have read an interesting article that says that comments of
today will often become statements and declaration and tags of
tomorrow, that is stuff that the interpreter/compiler/editor
understands. This means that such annotations of mine may be something
fit to become a syntax of the language. I don't have ideas on how such
syntax can be, if you have suggestions I'm listening.

Finally in modules that contain many different things, and where each
of them uses generally distinct modules, as a compromise I sometimes
write code like this:

import foo # used by baz()

def baz(n):
return foo(n) * 10
import bar # used by spam()

def spam(k):
return bar(k) - 20

My editor has a command that finds and lists me all the global imports
(not indented) of the module.

Bye,
bearophile
Nov 15 '08 #3
r0g
be************@lycos.com wrote:
r0g:
>a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...
b) Include them in each function individually.

This is a interesting topic, that requires some care.
Generally I suggest you put them at the top, so they can be found and
seen with less problems (*), it's the standard.
If a function is called only once in a while (like a plotting
function), and to import its module(s) it needs lot of time and memory
(like matplotlib), then you may move the import inside the function
itself, especially if such function isn't speed-critical.
(*)
I generally agree with the PEP8 but regarding this I don't follow it:
I feel free to put more than one of them on the same line:
import os, sys, ...
I generally list the built-in modules first, then the well known one
(pyparsing, numpy, etc), and then my ones or less known ones.

I also put a comment after each import, with the name of the function/
class it is used into:

import foo # used by baz()
import bar # used by spam()

...
def baz(n):
return foo(n) * 10
...
def spam(k):
return bar(k) - 20

Time ago I have read an interesting article that says that comments of
today will often become statements and declaration and tags of
tomorrow, that is stuff that the interpreter/compiler/editor
understands. This means that such annotations of mine may be something
fit to become a syntax of the language. I don't have ideas on how such
syntax can be, if you have suggestions I'm listening.

Finally in modules that contain many different things, and where each
of them uses generally distinct modules, as a compromise I sometimes
write code like this:

import foo # used by baz()

def baz(n):
return foo(n) * 10
import bar # used by spam()

def spam(k):
return bar(k) - 20

My editor has a command that finds and lists me all the global imports
(not indented) of the module.

Bye,
bearophile


Thanks for the suggestions guys. I hadn't thought about putting comments
after the imports, that's a good idea, although I guess you need to be
disciplined in keeping them up to date. All the same, given the
seemingly negligible performance hit and the nature of this particular
module I think I will probably go with includes within the functions
themselves anyway...

The module I am compiling is kind of a scrapbook of snippets for my own
development use, it has no coherent theme and I wouldn't be distributing
it or using the whole thing in a production environment anyway, just
copying the relevant functions into a new module when needed. I'm
thinking having the imports inline might make that process easier when I
do need to do it and once copied I can always move them out of the
functions declarations.

Having said that, having your editor trace these dependencies for you is
an interesting idea too. Which editor are you using? (not trying to
start an editor flame war anyone, shh!). Can this be done from idle or
are you aware of a python script that can do this maybe?

Thanks again,

Roger.
Nov 15 '08 #4
be************@lycos.com wrote:
r0g:
>a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...
b) Include them in each function individually.

This is a interesting topic, that requires some care.
Generally I suggest you put them at the top, so they can be found and
seen with less problems (*), it's the standard.
If a function is called ...[rarely] ... you may move the import inside
the function itself, especially if such function isn't speed-critical.
I would amend this advice by adding that you should (in such cases) put
a commented-out import at the top level (so you can look at the top of a
module's source and see what other modules it relies upon.

--Scott David Daniels
Sc***********@Acm.Org
Nov 15 '08 #5
On Nov 15, 9:08*pm, bearophileH...@lycos.com wrote:
I also put a comment after each import, with the name of the function/
class it is used into:

import foo # used by baz()
import bar # used by spam()
Why bother with the ()? Why bother at all? Surely this rapidly becomes
tedious clutter:
import xyz # used by abc(), def(), ghi(), ...
Do you remember to adjust the comment when a function/class is changed
so that it doesn't use the module any more?
...
def baz(n):
* * return foo(n) * 10
...
def spam(k):
* * return bar(k) - 20
Your modules are callable???
Time ago I have read an interesting article that says that comments of
today will often become statements and declaration and tags of
tomorrow, that is stuff that the interpreter/compiler/editor
understands. This means that such annotations of mine may be something
fit to become a syntax of the language.
I hope not.
I don't have ideas on how such
syntax can be, if you have suggestions I'm listening.
Suggestion: no such syntax!!
Nov 15 '08 #6
r0g wrote:
The module I am compiling is kind of a scrapbook of snippets for my own
development use, it has no coherent theme and I wouldn't be distributing
it or using the whole thing in a production environment anyway, just
copying the relevant functions into a new module when needed. I'm
thinking having the imports inline might make that process easier when I
do need to do it and once copied I can always move them out of the
functions declarations.
This is something of a special case, so I don't think the usual style guides
entirely apply. What I would do is keep the imports outside of the functions,
but put them before the functions that use them. Repeat the imports as
necessary. For example, if f() uses modules foo and bar, while g() uses only foo:

############################

import foo
import bar

def f():
...

############################

import foo

def g():
...

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Nov 15 '08 #7
Robert Kern wrote:
r0g wrote:
>The module I am compiling is kind of a scrapbook of snippets for my own
development use, it has no coherent theme and I wouldn't be distributing
it or using the whole thing in a production environment anyway, just
copying the relevant functions into a new module when needed. I'm
thinking having the imports inline might make that process easier when I
do need to do it and once copied I can always move them out of the
functions declarations.

This is something of a special case, so I don't think the usual style
guides entirely apply. What I would do is keep the imports outside of
the functions, but put them before the functions that use them.
Actually, I lie. What I really do is keep a Mercurial repository of all of the
snippets I use in separate files.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Nov 15 '08 #8
John Machin:
import foo # used by baz()
import bar # used by spam()

Why bother with the ()?
I code in other language too beside Python, in those languages there
are other things (like templates in D language) beside functions, so
my comment helps me remember that baz() is a function instead of a
template written in lowercase: baz!().

Why bother at all?
If I remove a function/class that uses baz from the module, I can go
at its top and find in a short time what imports to remove. Probably
there are other purposes too.

Do you remember to adjust the comment when a function/class is changed
so that it doesn't use the module any more?
Most of the times yes. Even if I forget doing it 2%-5% of the times,
it's worth it, for me. Notice that I have just shown what coding
practices seem currently good for me, for certain kinds of programs,
etc. Feel free to use your own.

Your modules are callable???
No, they aren't, it's a mistake of mine, sorry.

Time ago I have read an interesting article that says that comments of
today will often become statements and declaration and tags of
tomorrow, that is stuff that the interpreter/compiler/editor
understands. This means that such annotations of mine may be something
fit to become a syntax of the language.

I hope not.
Can you explain why you don't like my idea?

Bye,
bearophile
Nov 16 '08 #9
On Nov 16, 6:58*pm, bearophileH...@lycos.com wrote:
John Machin:
import foo # used by baz()
import bar # used by spam()
Why bother with the ()?

I code in other language too beside Python, in those languages there
are other things (like templates in D language) beside functions, so
my comment helps me remember that baz() is a function instead of a
template written in lowercase: baz!().
Why bother at all?

If I remove a function/class that uses baz from the module, I can go
at its top and find in a short time what imports to remove.
pychecker tells you about modules that are imported but not used.
Probably
there are other purposes too.
Do you remember to adjust the comment when a function/class is changed
so that it doesn't use the module any more?

Most of the times yes. Even if I forget doing it 2%-5% of the times,
it's worth it, for me. Notice that I have just shown what coding
practices seem currently good for me, for certain kinds of programs,
etc. Feel free to use your own.
Your modules are callable???

No, they aren't, it's a mistake of mine, sorry.
Time ago I have read an interesting article that says that comments of
today will often become statements and declaration and tags of
tomorrow, that is stuff that the interpreter/compiler/editor
understands. This means that such annotations of mine may be something
fit to become a syntax of the language.
I hope not.

Can you explain why you don't like my idea?
Yes. The vast majority of imports are unconditional and not done
dynamically via the __import__ built-in function and all the
information required about what function/class/method needs what
module to be imported is ALREADY in your source file. If you want to
faff about duplicating that in comments, feel free. However suggesting
that this be enshrined in language syntax is mind -boggling.
Nov 16 '08 #10
r0g <ai******@technicalbloke.comwrote:
I'm collecting together a bunch of fairly random useful functions I have
written over the years into a module. Generally speaking is it best to

a) Import all the other modules these functions depend on into the
modules global namespace by putting them at the top of the module or
should I...

b) Include them in each function individually.

Stylistically I like the idea of b) better as it makes for easy
refactoring in the future but is there any drawback to doing it this
way? i.e. does it get repeatedly parsed, use more memory, become
inefficient when several functions that use the same includes are
invoked etc Or does it really not matter?
b) has the disadvantage / possible advantage that if the module it
depends on isn't present then it doesn't complain until run time. a)
will always complain at compile time (ie when the script is loaded).

I tend to put all my imports on the top, and I tend to write them like
this

from a_module import fn1, fn2, fn3

Which fails definitively at compile time rather than waiting for the
fn1() to be called.

Importing things into your local namespace is also the quickest, but
that isn't why I do it!

There are arguments against doing this, which I'm sure you'll hear
shortly ;-)

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Nov 16 '08 #11
Scott David Daniels wrote:
I would amend this advice by adding that you should (in such cases) put
a commented-out import at the top level (so you can look at the top of a
module's source and see what other modules it relies upon.
That's what your editor's search function is for.
Nov 17 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: matty | last post by:
Go away for a few days and you miss it all... A few opinions... Programming is a craft more than an art (software engineering, not black magic) and as such, is about writing code that works,...
52
by: Tony Marston | last post by:
Several months ago I started a thread with the title "What is/is not considered to be good OO programming" which started a long and interesting discussion. I have condensed the arguments into a...
3
by: Erik De Keyser | last post by:
Hi group, I have a couple of projects with up to 8 forms. On most projects I write the code on each form with no modules. The last project I use 1 module and minimal code on each form , in fact...
5
by: John Ladasky | last post by:
Hi, folks, At the beginning of 2003, I was a frustrated computer user, and lapsed programmer, with problems to solve that screamed for programming. Thanks to the Python language and community, I...
27
by: Matt Kruse | last post by:
Since this topic has come up several times in other threads, I thought I'd make a separate thread and gather opinions from (hopefully) a more varied range of newsgroup participants. What are...
33
by: MLH | last post by:
I've read some posts indicating that having tons of GV's in an Access app is a bad idea. Personally, I love GVs and I use them (possibly abuse them) all the time for everything imaginable - have...
6
by: MLH | last post by:
I have frmMainMenu with the following two code lines invoked on a button click... 2420 DoCmd.OpenForm "frmVehicleEntryForm", A_NORMAL, , , A_ADD, A_NORMAL 2440 DoCmd.GoToRecord , , A_NEWREC ...
206
by: WaterWalk | last post by:
I've just read an article "Building Robust System" by Gerald Jay Sussman. The article is here: http://swiss.csail.mit.edu/classes/symbolic/spring07/readings/robust-systems.pdf In it there is a...
7
by: alito | last post by:
Hi all, I am new to using packages to group my modules. I can't figure out how to run a module that uses relative imports without writing a wrapper that imports that module. Everything I try...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.