How to import only one module in a package when the package__init__.py has already imports the modul

S

Steven D'Aprano

I can not use the above approach as I mentioned its problem in my
previous message.

Either I have not seen it, or I have not understood it, but I don't
understand why you can not use this approach.

This artificially introduces the constraint that the file name can not
be the same as the class/function name. There is no constraint like this
if I can C++.

It is not a constraint, it is a convention. You are free to ignore it if
you like.


Some people don't like writing "glob.glob" (for example). Some people
would like to see Python ban modules with the same name as objects inside
them, to avoid this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'datetime.datetime' has no attribute
'datetime'


You seem to be inconsistent -- you say you want to name the file the same
as the function in it, so you know which file to look for a function, but
then you complain about writing:

test.A.A

so when we suggest naming A.py a.py, so you can write:

test.a.A

you complain about that too. Frankly, I think you are just complaining
because Python isn't C++.

This sentence is confusing. Can you spell out what you mean?

If you supply a package

test/
+-- __init__.py
+-- A.py
+-- B.py


there is nothing stopping your users from doing this:

import test.A as A
import test.B as SomethingElse


[...]
I have defined 'long' in one of my previous message. I consider a file
long, when it does not fit in one or two screen. Basically, I want to
get a whole picture of the file after glancing of the file.

You must only write incredibly trivial programs then.

There is more to understanding a program than understanding one single
function. Any serious function will call other functions. To get the
whole picture, you have to understand them too. Your requirement simply
shifts the burden from "open one file, and read ten functions" to "open
ten files, and read ten functions".
 
S

Steven D'Aprano

You misunderstood me.

If there are multiple functions or classes in a file, when I change
variables in a function/class, I have to make sure that they are not in
other functions or classes.

No you don't.

def f(x):
return x+1

def g(x):
return x-1


If I choose to refactor f() and change "x" to "y", why do I care about
the internal variable inside g()?



Oh wait, I get it... you want to do a global search-and-replace over the
entire file. *face-palm*

If your functions are less than one-screen full, why do you need a global
replacement? Global replacement risks changing words in docstrings,
comments etc that it shouldn't.
 
S

Steven D'Aprano

So python would not be able to accommodate my preference one
class/function per file?

Of course it does! You can do that RIGHT NOW -- just put one class per
file.
I.e., I have to use something like 'from spam
import spam' or 'spam.spam()',

How else do you expect to use the class if you don't import it?

or accept that the filename is not the
same as the class/function name.

So let me see...

You don't want to write "import spam; spam.spam()"
You don't want to write "from spam import spam; spam()"
You don't want to write "from Spam import spam; spam()"
You don't want to write "from spam import Spam; Spam()"

What exactly do you want?
 
R

Robert Kern

Ben said:
Would I be correct in assuming you make an exception for the package
importing one of the modules in the package, and thereby making that
module's identifier exposed?

package_foo/
__init__.py
module_bar.py

$ cat foo/__init__.py
import module_bar

Now the name ‘package_foo.module_bar’ will get the identifier already
assigned within ‘package_foo/__init__.py’, but that identifier is the
module anyway.

Yes.

--
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
 
P

Peng Yu

Either I have not seen it, or I have not understood it, but I don't
understand why you can not use this approach.

The problem is when you test a package you want to 'import test.A'
rather than 'import test'. Having such __init__.py does not allow you
to import only 'test.A'. This cause artificial dependence.
It is not a constraint, it is a convention. You are free to ignore it if
you like.

I'm ignoring this convention now. But I have to call a function like
glob.glob, which I also feel inconvenient.
Some people don't like writing "glob.glob" (for example). Some people
would like to see Python ban modules with the same name as objects inside
them, to avoid this error:

Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
AttributeError: type object 'datetime.datetime' has no attribute
'datetime'


You seem to be inconsistent -- you say you want to name the file the same
as the function in it, so you know which file to look for a function, but
then you complain about writing:

test.A.A

so when we suggest naming A.py a.py, so you can write:

test.a.A

you complain about that too. Frankly, I think you are just complaining
because Python isn't C++.

I'm not complaining. I just wish there is a walkaround. In C++, I
still have to write some script to make sure the directory hierarchy
is consistent with the namespace, because C++ doesn't impose the
constraint that the directory hierarchy is the same as the namespace.
But it seems that is no such walkaround in python for my case, because
python binds namespace to directory hierarchy.
If you supply a package

test/
+--  __init__.py
+--  A.py
+--  B.py


there is nothing stopping your users from doing this:

import test.A as A
import test.B as SomethingElse

First, this is a redudancy---'A' appears twice. Second, you can not do
something like the following, because name A from the two name space
is conflict.

import test.A as A
import test2.A as A

[...]
I have defined 'long' in one of my previous message. I consider a file
long, when it does not fit in one or two screen. Basically, I want to
get a whole picture of the file after glancing of the file.

You must only write incredibly trivial programs then.

There is more to understanding a program than understanding one single
function. Any serious function will call other functions. To get the
whole picture, you have to understand them too. Your requirement simply
shifts the burden from "open one file, and read ten functions" to "open
ten files, and read ten functions".

I insist on having screen long functions or classes, because they have
less number of states compare with long ones. This allows me to test
all the states of them to make sure they are bug free. It is
reasonable to assume the log of the number of states of a function or
a class is proportional to it length. Hence, when a function or a
class is long, you will never be able to test all its states.

I don't have to put all related functions in a single file. With vim
and ctags, you should be able to jump to the definition of any
function or class from the place where it is used. So putting single
class/function in a file does not give me any extra 'burden' than if I
put them in the same file.
 
P

Peng Yu

Of course it does! You can do that RIGHT NOW -- just put one class per
file.


How else do you expect to use the class if you don't import it?



So let me see...

You don't want to write "import spam; spam.spam()"
You don't want to write "from spam import spam; spam()"
You don't want to write "from Spam import spam; spam()"
You don't want to write "from spam import Spam; Spam()"

What exactly do you want?

When I define class spam in file spam.py, I want to call it by

import spam
spam()

If spam.py is in dir/, then I want to call it by

import dir.spam

dir.spam()
 
P

Peng Yu

No you don't.

def f(x):
   return x+1

def g(x):
   return x-1


If I choose to refactor f() and change "x" to "y", why do I care about
the internal variable inside g()?

What I mean was, for example, I only want to change 'x' in f() to 'y',
but not 'x' in g() to 'y', because the meaning of 'x' in f() and 'x'
in g() may represent different things. If both f() and g() are in the
same file, I have to make sure that I only replace 'x' in f() but not
in g(). However, if I only have f() in a file, I can simply replace
all x in the file without worrying replacing 'x' in g(). Is this
clear?
Oh wait, I get it... you want to do a global search-and-replace over the
entire file. *face-palm*

Yes. You get it.
If your functions are less than one-screen full, why do you need a global
replacement? Global replacement risks changing words in docstrings,
comments etc that it shouldn't.

My variables in general are not as short as a single letter, like 'x',
and is descriptive. In general, they will not appear in docstrings,
unless the ones in docstrings mean the same thing, in which case it is
OK to replace the variable and the one in docstrings.
 
R

Robert Kern

Peng said:
On Sat, Oct 31, 2009 at 11:40 PM, Steven D'Aprano


Yes. You get it.

In any capable programmer's editor, it should not be hard to do a local
search-and-replace over just the one function.

--
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
 
R

Robert Kern

Peng said:
When I define class spam in file spam.py, I want to call it by

import spam
spam()

If spam.py is in dir/, then I want to call it by

import dir.spam

dir.spam()

That's just not how Python imports work.

--
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
 
S

Steven D'Aprano

In any capable programmer's editor, it should not be hard to do a local
search-and-replace over just the one function.

Given the OP's stated claim that all his functions are less than a screen
in size, Notepad could do it, with just the tiniest amount of manual
effort.
 
S

Steven D'Aprano

It is
reasonable to assume the log of the number of states of a function or a
class is proportional to it length. Hence, when a function or a
class is long, you will never be able to test all its states.



def f(n):
return n + 5


def g(n):
x = n + 1
x += 1
x += 1
x += 1
return x + 1


Function g() has five times the length (in lines) as f(). Does it require
five times the testing? Obviously not. In fact, there's no easy way to
test the internal state of the function from outside, because x is local
to g(). You can't test the value of x from outside, because x is not
exposed to the outside.

The complexity of testing functions is roughly proportional to the number
of paths through the function, not the number of lines. Both f() and g()
have a single path through the function and therefore require the same
amount of testing.

The simplest estimate of the number of paths in a function is the number
of if...else statements. Each pair *doubles* the number of paths:

def func():
if cond1: A
else: B
if cond2: C
else: D
if cond3: E
else: F

There are 2**3 paths that need testing:

ACE ACF ADE ADF BCE BCF BDE BDF


Or consider this example:

def func(x, cond):
for f in [A, B, C, D, E, F]:
if cond(x): x = f(x)


This function has two lines only, but clearly there could be as many as
128 paths that need testing. Ideally your test data should visit each one
of these paths.
 

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

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,150
Members
46,697
Latest member
AugustNabo

Latest Threads

Top