That's what the Python style guides advise. They don't seem to like
def frob(x):
import re
if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace
with the names of all your imports. What's the point of that? It
gets worse when you want to do something like
def dispatch(obj):
from types import *
if type(obj) == ListType: obj_list(obj)
elif type(obj) == FunctionType: obj_fcn(obj)
...
here you actually get a syntax warning that "from ... import *" is not
ALLOWED except at the module level. So the pollution is really
serious in that case, you're spewing all the names from the imported
module into your own module. And I know that "import *" is considered
uncool these days, but sometimes you really do want to just grab all
those symbols, and the whole point of wanting the import inside the
function is to contain the big import to a limited scope where they
won't conflict with your own symbols.
So what's the reason for the syntax warning, and for the convention of
putting the imports at the top of the module? 9 2794
Paul Rubin <http://ph****@NOSPAM.invalid> writes: That's what the Python style guides advise. They
^^^^
I do wish people would stop using this word in this sort of context...
don't seem to like
def frob(x): import re if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace with the names of all your imports. What's the point of that?
What's the problem with that?
It gets worse when you want to do something like
def dispatch(obj): from types import * if type(obj) == ListType: obj_list(obj) elif type(obj) == FunctionType: obj_fcn(obj) ...
here you actually get a syntax warning that "from ... import *" is not ALLOWED except at the module level.
The problem HERE is for nested scopes; it's impossible to know in
def f():
from baz import *
def g():
return y
where y is coming from (i.e. is it a captured binding or a global).
So what's the reason for the syntax warning, and for the convention of putting the imports at the top of the module?
I think putting imports at the top is just so you can find them
easily, and at a glance see which modules a given module imports.
Cheers,
mwh
--
"The future" has arrived but they forgot to update the docs.
-- R. David Murray, 9 May 2000
Paul Rubin wrote: That's what the Python style guides advise. They don't seem to like
def frob(x): import re if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace with the names of all your imports. What's the point of that?
Maintainability. It's also well understood that there are potential
benefits to the approach you show above, late-loading of code being
one of them (which can improve startup time for certain apps), but
as maintainability should almost always be the primary consideration,
the standard advice is to put stuff together at the top where it's
clear to maintainers which modules are used in the code (in other
words, what a given module is coupled to).
-i've-been-playing-the-esp-game-so-i-channeled-the-style-guide-authors
-Peter
[Peter Hansen] Paul Rubin wrote:
That's what the Python style guides advise. They don't seem to like
def frob(x): import re if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace with the names of all your imports. What's the point of that?
Maintainability. It's also well understood that there are potential benefits to the approach you show above, late-loading of code being one of them (which can improve startup time for certain apps), but as maintainability should almost always be the primary consideration, the standard advice is to put stuff together at the top where it's clear to maintainers which modules are used in the code (in other words, what a given module is coupled to).
I never understood this "standard advice", nor how it is related to
maintainability. What makes a module significantly more maintainable
by merely grouping `import' statements at the beginning? What is it so
crucial to know that the `re' module is used, or not, in a program? It
looks like a tiny detail to me.
If for some strange reason I urgently needed to know everything that a
program imports, I guess I would then `grep' the source for the word
`import'i, or just search with an editor! :-) This is surely not a need
I often have, and for from enough for justifying the convention.
If within a `def', I will often use a module which I do not use
elsewhere in a program, there is no reason to make it global. Global
variables should be avoided on the average, and moreover, Python is
faster at accessing a local than a global.
I'm not really crusading for either method, but maybe a bit against
the mere existence of the "standard advice", unless it acquires some
better justification. Of course, "maintainability" is a virtue, but the
relation between maintainability and the "standard advice" is asserted
as if it were to be evident, without explanation.
--
François Pinard http://www.iro.umontreal.ca/~pinard
"Paul Rubin" <http://ph****@NOSPAM.invalid> wrote in message
news:7x************@ruckus.brouhaha.com... That's what the Python style guides advise. They don't seem to like
def frob(x): import re if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace with the names of all your imports. What's the point of that? It gets worse when you want to do something like
def dispatch(obj): from types import * if type(obj) == ListType: obj_list(obj) elif type(obj) == FunctionType: obj_fcn(obj) ...
here you actually get a syntax warning that "from ... import *" is not ALLOWED except at the module level. So the pollution is really serious in that case, you're spewing all the names from the imported module into your own module. And I know that "import *" is considered uncool these days, but sometimes you really do want to just grab all those symbols, and the whole point of wanting the import inside the function is to contain the big import to a limited scope where they won't conflict with your own symbols.
So what's the reason for the syntax warning, and for the convention of putting the imports at the top of the module?
The reason to put imports at the top of the module
is that, in general, imported modules are global resources. That's
also why it's not an issue to insert them in the module level
namespace.
Also, there are certain very common program tasks, such
as creating a subclass, where the superclass has to be
available at module load time. If it's in another module, that
module has to be imported before defining the class.
That said, if a module isn't a global resource then there's
no particular reason to put the symbol in the module
symbol table. I use __import__ in my version of FIT
to import fixtures into a dictionary, for example. I prefer
that technique to attempting to exec a constructed
import statement precisely because I don't have any
control over the names of the imported modules.
From foobar import * is a specialized case that
should be used only when you know what the module
is going to import. If you don't want the scatter shot
loading, then just import foobar, and reference foobar.whatever
whenever you need a symbol. No one is holding an
assault weapon to your head to make you use import *
after all.
If you're a control freak (or your program analysis tools
barf on import *), you can always put assignments
for the symbols you're going to use after the imports.
That makes it explicit.
John Roth
François Pinard wrote: [Peter Hansen] Maintainability. It's also well understood that there are potential benefits to the approach you show above, late-loading of code being one of them (which can improve startup time for certain apps), but as maintainability should almost always be the primary consideration, the standard advice is to put stuff together at the top where it's clear to maintainers which modules are used in the code (in other words, what a given module is coupled to). I never understood this "standard advice", nor how it is related to maintainability. What makes a module significantly more maintainable by merely grouping `import' statements at the beginning? What is it so crucial to know that the `re' module is used, or not, in a program? It looks like a tiny detail to me.
"re" is not a good example of the above, though there might also be
very good but different reasons to import re at the top. Often it
is used in several different places, and that would mean duplication
(and a tiny waste of time) if you always imported it at the beginning
of each method, or even just before it was used.
A better example is application-specific modules. "Hiding" those down
in the individual methods that use them makes it much more difficult
to see the coupling between modules.
More coupling means less maintainability.
Second reason: if you put your import, which you use in only one place,
locally in the method where it's used, then modify the code so that
another method also uses the module, you will end up with two imports.
More duplication means less maintainability.
If within a `def', I will often use a module which I do not use elsewhere in a program, there is no reason to make it global. Global variables should be avoided on the average, and moreover, Python is faster at accessing a local than a global.
As you probably know, I almost never put performance anywhere near the
level I put other considerations, so if we still differ on this matter,
perhaps it's because of different values.
-Peter
[Peter Hansen] François Pinard wrote:
A better example is application-specific modules. "Hiding" those down in the individual methods that use them makes it much more difficult to see the coupling between modules.
Agreed indeed, the coupling between modules is less explicit then.
More coupling means less maintainability.
On the other hand, the location of `import' has no effect on the amount
of coupling.
Second reason: if you put your import, which you use in only one place, locally in the method where it's used, then modify the code so that another method also uses the module, you will end up with two imports. More duplication means less maintainability.
Maybe not. I may have many functions each having a local counter, and
despite all the duplication, using a single global counter instead would
not imply more maintainability. Locality (of definition and use) is
often best for maintainability, even if it means random duplication.
There is no definitive rule about what is good or bad, and this is where
good taste comes in, which turns all this program writing into an art! Global variables should be avoided on the average, and moreover, Python is faster at accessing a local than a global.
As you probably know, I almost never put performance anywhere near the level I put other considerations, so if we still differ on this matter, perhaps it's because of different values.
Performance is not to be a primary concern on the average, quite
agreed! Still, a few simple habits are easily acquired that yield
faster programs on average, which happily coincide with good programming
practices. I consider this coincidence as a reason to rejoice! :-)
--
François Pinard http://www.iro.umontreal.ca/~pinard
François Pinard wrote: [Peter Hansen] More coupling means less maintainability. On the other hand, the location of `import' has no effect on the amount of coupling.
I think I can make a good argument that it does. Try this on for size:
if the import of module B is in several methods of module A, then each of
those methods is directly coupled to module B. You've got several
instances of coupling. Now move the duplicate imports up to the top
of module A. Each method is now coupled only to module A, which of
course all methods in that module are, but only module A has any
coupling to module B.
When I analyze coupling, I consider the links to have both strength
and quantity. Generally a reduction in quantity is just as useful
as a reduction in strength of coupling, IME. Second reason: if you put your import, which you use in only one place, locally in the method where it's used, then modify the code so that another method also uses the module, you will end up with two imports. More duplication means less maintainability.
Maybe not. I may have many functions each having a local counter, and despite all the duplication, using a single global counter instead would not imply more maintainability. Locality (of definition and use) is often best for maintainability, even if it means random duplication.
Unfortunately you lost me with the example. I can't see the connection
between having separate local counters and a single global counter,
since presumably the logic requires either one or the other. (I trust
you had a valid point but I missed it, sorry.)
There is no definitive rule about what is good or bad, and this is where good taste comes in, which turns all this program writing into an art!
Very true of course, as with all design.
-Peter
[Peter Hansen] When I analyze coupling, I consider the links to have both strength and quantity. Generally a reduction in quantity is just as useful as a reduction in strength of coupling, IME.
This sounds all quite reasonable! :-)
Unfortunately you lost me with the example. [...] (I trust you had a valid point but I missed it, sorry.)
Thanks for the confidence! :-) Let me not insist with the example, as
I'm not trying to make a point here :-). As long as we agree to seek for
aesthetic programs, the methods and tastes of the various artists may
differ, and the diversity is one more source of interest. Keep happy!
--
François Pinard http://www.iro.umontreal.ca/~pinard
Michael Hudson wrote: def frob(x): import re if re.search('sdf[234]xyz', x): ...
instead preferring that you pollute your module's global namespace with the names of all your imports. What's the point of that? What's the problem with that?
(1) It breaks code encapsulation. Well, perhaps
"breaks" is too strong a word, but it makes data hiding
more difficult. Unless you jump through hoops to remove
all traces of the objects you import, modules that you
import will be visible to those that import you.
(2) It is messy. The whole point of nested scopes is to
make objects visible only to the objects that need
them. If only one function needs the import, why force
it to be visible to all the others?
(3) There was clearly a need (or at least a wish) to be
able to hide imported objects from importing modules.
The usual way of doing this is:
from spam import public as _notpublic
Making the import local to the calling function works
well too.
I sometimes delete the binding when I'm done:
from spam import public
# use public in here
del public
although there are disadvantages to this method.
[snip] The problem HERE is for nested scopes; it's impossible to know in
def f(): from baz import * def g(): return y
where y is coming from (i.e. is it a captured
binding > or a global).
Why is this any different from the following top-level
code:
# module baz:
y = "spam spam spam" y= "I don't like spam" from baz import *
Where is the binding y coming from? The question of
whether this code is at the top-level or in a function
definition is a red herring.
It seems to me that forbidding imports except at the
top level is an arbitrary restriction. Using import
insided function definitions might not work for some
people, but it works for others.
--
Steven D'Aprano This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Stian Søiland |
last post by:
all examples performed with:
Python 2.3+ (#2, Aug 10 2003, 11:09:33)
on linux2
(2, 3, 0, 'final', 1)
This is a recursive import:
|
by: Manlio Perillo |
last post by:
Hi.
I'm a new user of Python but I have noted a little problem.
Python is a very good language but it is evolving, in particular its
library is...
|
by: Grant D. Watson |
last post by:
If this has been answered before, or if my terminology is off, please bear with
me; my Python experience is limited to use in one class and to...
|
by: Jacek Generowicz |
last post by:
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative...
|
by: didier.doussaud |
last post by:
I have a stange side effect in my project :
in my project I need to write "gobal" to use global symbol :
....
import math
....
def f() :...
|
by: Mudcat |
last post by:
I have a directory structure that contains different modules that run
depending on what the user selects. They are identical in name and
structure,...
|
by: Anders J. Munch |
last post by:
Now 2.5 is out, and we have a syntax for explicit relative imports
(PEP 328, http://www.python.org/dev/peps/pep-0328/, in case anyone
wasn't paying...
|
by: lemke_juergen |
last post by:
Hi everyone,
I define some vars and functions in a "support" module which gets
called from my
main app module. Using Python 2.5.
I import all...
|
by: robert |
last post by:
I get python crashes and (in better cases) strange Python exceptions when (in most cases) importing and using cookielib lazy on demand in a thread....
|
by: Kemmylinns12 |
last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
|
by: Naresh1 |
last post by:
What is WebLogic Admin Training?
WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
|
by: antdb |
last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine
In the overall architecture, a new "hyper-convergence" concept was...
|
by: Matthew3360 |
last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function.
Here is my code.
...
|
by: Matthew3360 |
last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
|
by: Arjunsri |
last post by:
I have a Redshift database that I need to use as an import data source. I have configured the DSN connection using the server, port, database, and...
|
by: WisdomUfot |
last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
|
by: Oralloy |
last post by:
Hello Folks,
I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA.
My problem (spelled failure) is with the...
|
by: BLUEPANDA |
last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS...
| |