where is best place for import statements?

M

Matthew Wilson

Hi-


I'm writing a bunch of classes, several of which need functions and
variables defined in the math module. In some instances, I'm going to
import my module like this:

import myshapes

and then in others, I'll do:

from myshapes import Circle

or even:

from myshapes import *

How do I make sure that no matter how I import stuff from myshapes.py, I
always also import the math module? Should I write all of my functions
like so:

def foo1():
import math
return math.pi

def foo2():
import math
return 2*math.pi

and all my classes like this:

class Circle:
def __init__(self,x, y, r):
import math
self.circumference = 2*r*math.pi

Is this the way to solve the problem?


Thanks for the help.
 
J

John Roth

Matthew Wilson said:
Hi-


I'm writing a bunch of classes, several of which need functions and
variables defined in the math module. In some instances, I'm going to
import my module like this:

import myshapes

and then in others, I'll do:

from myshapes import Circle

or even:

from myshapes import *

How do I make sure that no matter how I import stuff from myshapes.py, I
always also import the math module? Should I write all of my functions
like so:

def foo1():
import math
return math.pi

def foo2():
import math
return 2*math.pi

and all my classes like this:

class Circle:
def __init__(self,x, y, r):
import math
self.circumference = 2*r*math.pi

Is this the way to solve the problem?

Your cure would probably solve the problem, but I
consider it much worse than the disease of having
to remember to stick the proper import statement
at the front of the module. You'll get at most one
error in each module where you forget to do that.

In general, importing a module at other than the
module level is something you do in very specialized
circumstances: when you need either a dynamic or
a conditional import.

John Roth
 
M

Matthew Wilson

Your cure would probably solve the problem, but I
consider it much worse than the disease of having
to remember to stick the proper import statement
at the front of the module. You'll get at most one
error in each module where you forget to do that.

In general, importing a module at other than the
module level is something you do in very specialized
circumstances: when you need either a dynamic or
a conditional import.

John Roth

So, instead of scattering all those import statements throughout my
file, I ought to just put them at the top of the file, right after the
module description?

And, if I decide to do something like

from mymod import Circle

Then it's up to me to remember to first do

import math

Is that right?
 
J

John Roth

Matthew Wilson said:
So, instead of scattering all those import statements throughout my
file, I ought to just put them at the top of the file, right after the
module description?

And, if I decide to do something like

from mymod import Circle

Then it's up to me to remember to first do

import math

At that point, it doesn't matter. It only matters when you go to
use it. However you organize the block of imports at the top
of the file will usually work; if there's a lot, I find alphabetizing
them sometimes helps, or sometimes putting the standard ones
first.

The one caveat to that is with modules that have circular
dependencies, but that's a whole different set of problems than
the one I think you're talking about.

John Roth
 
P

Peter Otten

Matthew said:
How do I make sure that no matter how I import stuff from myshapes.py, I
always also import the math module? Should I write all of my functions

Literal answer: put

from math import *

into myshapes.py, and access variables and functions like so:
#test1.py
import myshapes
myshapes.pi
myshapes.sin(alpha)
myshapes.whatever
....
#end test1.py

However, I've got the impression that you think that in order to *use* your
myshapes module, you have to import the math module.

That is wrong, e. g.:

#myshapes.py
import math
class Circle:
def __init__(self, x, y, r):
self.circumference = 2*r*math.pi
#end myshapes py>

You can use this in a script that does *not* import math:

#test.py
import myshapes
veryRoundCircle = Circle(0, 0, 1.0)
print veryRoundCircle.circumference
#end test.py

The general idea is to design modules as orthogonal as possible, i. e. it is
good design for a module to provide its functionality without imposing
restrictions on the client code. The usage of math.pi is only an
implementation detail, that the user of myshape should not have to bother
about. If you later add a Rectangle, you could provide a, say, turn(angle)
method, again with the effect of *eliminating* the need for math.sin() etc.
in client code.

As an aside, think about making circumference in the above example a method,
if you also store the radius in the instance. If you later change the
radius, the circumference is thus updated automatically. General rule:
avoid redundant data.

Peter
 
G

Graham Ashton

I'm writing a bunch of classes, several of which need functions and
variables defined in the math module. In some instances, I'm going to
import my module like this:

import myshapes

and then in others, I'll do:

from myshapes import Circle

You're best off avoiding importing things with from, except under
certain specific circumstances. If you use it to import classes or
variables from other modules then you run the risk of circular
imports, which are horrid.

It's generally considered better style to do this instead:

import myshapes

circle = myshapes.Circle()

as (apart from avoiding the technical problems of "from") you then
benefit from the contextual clues that the myshapes prefix gives
you. It's a boon for others reading your code, or for yourself a few
months down the line.
from myshapes import *

Don't even go there, it's usually a bad habit. It makes for difficult
to follow code, and can also reduce performance under some
circumstances.
How do I make sure that no matter how I import stuff from myshapes.py, I
always also import the math module? Should I write all of my functions
like so:

If myshapes imports math, then users of myshapes that don't need to
refer to math themselves will never need to import it themselves. The
convention is to group your import statements at the top of your
module.

See the Imports section of PEP 8 for more:

http://www.python.org/peps/pep-0008.html

Hope that helps.
 
G

Graham Ashton

Literal answer: put

from math import *

into myshapes.py, and access variables and functions like so:
import myshapes
myshapes.pi
myshapes.sin(alpha)

Why on earth would you want to do that? If somebody wants to get the
value of PI why would you want them to use anything other than math.pi
directly? I realise you might be using this as an example of what you
*could* do, but I don't think it's good practice.

If I was reading code and saw myshapes.sin, and I new that math.sin
existed (which I do as it's in the standard library), I would
naturally assume that it was either an alternative implementation
(which I wouldn't trust), or that it did something else entirely.
 
P

Peter Otten

Graham said:
Why on earth would you want to do that? If somebody wants to get the
value of PI why would you want them to use anything other than math.pi
directly? I realise you might be using this as an example of what you
*could* do, but I don't think it's good practice.

Definitely not. I should have used a stronger disclaimer than "literal
answer".

I have a "builtins" module for the interpreter (and a few quick and dirty
scripts) and always use it like that:

from misc import *

As the origin of the imported symbols is thus hidden, there is no potential
for confusion that exceeds the general star import.
If I was reading code and saw myshapes.sin, and I new that math.sin
existed (which I do as it's in the standard library), I would
naturally assume that it was either an alternative implementation
(which I wouldn't trust), or that it did something else entirely.

You are stressing the universality of sin() a bit much for my taste. Did you
know that Python is shipped with two flavours of trigonometrical functions
(float and complex)? I think Numeric has yet another one. So you could
think of it this way: Let myshapes pick the appropriate sin (pun not
intended but welcome) for me.

Again, as I think I made clear in my previous post, if I were to implement
myshapes, I would strive to hide sin() as an implementation detail.

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top