embarrassing class question

B

Brendan

Two modules:
x.py:
class x(object):
pass

y.py:
from x import x
class y(x):
pass

Now from the python command line:['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']

I do not understand why class 'x' shows up here.
 
J

Jonas H.

Two modules:
x.py:
class x(object):
pass

y.py:
from x import x
class y(x):
pass

Now from the python command line:['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']

I do not understand why class 'x' shows up here.

Because that's how `import` behaves. It imports *every* member of the
module into the importing module's global namespace (except for
attributes that start with an underscore).

You can specify the attributes that shall be import with a star-import
by settings __all__. In your case, you would add `__all__ = ['y']` to y.py.

Jonas
 
C

Carl Banks

Two modules:
x.py:
class x(object):
    pass

y.py:
from x import x
class y(x):
    pass

Now from the python command line:>>> import y
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']

I do not understand why class 'x' shows up here.

Because you imported it into the namespace, which is what the import
statement does. dir() shows you what's in the namesace; therefore it
lists x. dir() doesn't care, and can't know, if something was defined
in a namespace, or merely imported.

If it bothers you, you can put "del x" after the class y definition,
but I recommend against doing that in general. If there's a reference
to x inside a function that function will raise an exception if
called, because it expects x to be inside the namespace.


Carl Banks
 
B

Brendan

Two modules:
x.py:
class x(object):
    pass
y.py:
from x import x
class y(x):
    pass
Now from the python command line:>>> import y
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.

Because you imported it into the namespace, which is what the import
statement does.  dir() shows you what's in the namesace; therefore it
lists x.  dir() doesn't care, and can't know, if something was defined
in a namespace, or merely imported.

If it bothers you, you can put "del x" after the class y definition,
but I recommend against doing that in general.  If there's a reference
to x inside a function that function will raise an exception if
called, because it expects x to be inside the namespace.

Carl Banks- Hide quoted text -

- Show quoted text -

So it must never make sense to put subclasses in separate modules?
 
E

Ethan Furman

Jonas said:
Two modules:
x.py:
class x(object):
pass

y.py:
from x import x
class y(x):
pass

Now from the python command line:
import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']

I do not understand why class 'x' shows up here.

Because that's how `import` behaves. It imports *every* member of the
module into the importing module's global namespace (except for
attributes that start with an underscore).

Um, no. (unless you do "from <whatever> import *" at the module level)

What it does is add whatever you imported into the namespace where you
imported it.

Because y.py has "from x import x" the x class from x.py is added to the
y.py namespace.

~Ethan~
 
C

Chris Rebert

Two modules:
x.py:
class x(object):
    pass
y.py:
from x import x
class y(x):
    pass
Now from the python command line:>>> import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.

Because you imported it into the namespace, which is what the import
statement does.  dir() shows you what's in the namesace; therefore it
lists x.  dir() doesn't care, and can't know, if something was defined
in a namespace, or merely imported.

If it bothers you, you can put "del x" after the class y definition,
but I recommend against doing that in general.  If there's a reference
to x inside a function that function will raise an exception if
called, because it expects x to be inside the namespace.

Carl Banks

So it must never make sense to put subclasses in separate modules?

Limiting yourself to one class per module is neither mandatory nor
common in Python. Python is not Java.

Cheers,
Chris
 
R

Robert Kern

Two modules:
x.py:
class x(object):
pass
y.py:
from x import x
class y(x):
pass
Now from the python command line:>>> import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.

Because you imported it into the namespace, which is what the import
statement does. dir() shows you what's in the namesace; therefore it
lists x. dir() doesn't care, and can't know, if something was defined
in a namespace, or merely imported.

If it bothers you, you can put "del x" after the class y definition,
but I recommend against doing that in general. If there's a reference
to x inside a function that function will raise an exception if
called, because it expects x to be inside the namespace.

Carl Banks

So it must never make sense to put subclasses in separate modules?

Of course it can make sense to put subclasses in separate modules, just for
other reasons.

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

Ian

So it must never make sense to put subclasses in separate modules?

It doesn't matter to Python whether the subclass is in the same module
or imported. Do it whichever way makes the most sense to you from a
code organization perspective.
 
B

Brendan

Jonas said:
Two modules:
x.py:
class x(object):
     pass
y.py:
from x import x
class y(x):
     pass
Now from the python command line:
import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.
Because that's how `import` behaves. It imports *every* member of the
module into the importing module's global namespace (except for
attributes that start with an underscore).

Um, no.  (unless you do "from <whatever> import *" at the module level)

What it does is add whatever you imported into the namespace where you
imported it.

Because y.py has "from x import x" the x class from x.py is added to the
y.py namespace.

~Ethan~- Hide quoted text -

- Show quoted text -

So what is usually done to prevent this? (In my case not wanting class
x added to the y.py namespace)
It seems sloppy.
 
C

Carl Banks

Two modules:
x.py:
class x(object):
    pass
y.py:
from x import x
class y(x):
    pass
Now from the python command line:>>> import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.
Because you imported it into the namespace, which is what the import
statement does.  dir() shows you what's in the namesace; therefore it
lists x.  dir() doesn't care, and can't know, if something was defined
in a namespace, or merely imported.
If it bothers you, you can put "del x" after the class y definition,
but I recommend against doing that in general.  If there's a reference
to x inside a function that function will raise an exception if
called, because it expects x to be inside the namespace.

So it must never make sense to put subclasses in separate modules?

Putting a subclass in the same module simply because you don't want it
to appear in some other module's namespace is not a good idea, IMO.
Sometimes it makes sense to put the subclass in another module, it
depends on the organization of the project.

I'm not sure how familiar you are with Python's object and namespace
systems. I assumed you were using dir() to see what objects were
defined in a module, and were disappointed to see x in the listing
also, but maybe you're under the impression that there is a lot of
duplicated data? Not really: a namespace contains references
(pointers) and so takes up a minimal amount of space, not worth
worrying about.


Carl Banks
 
R

Robert Kern

Jonas said:
On 10/21/2010 08:09 PM, Brendan wrote:
Two modules:
x.py:
class x(object):
pass
y.py:
from x import x
class y(x):
pass
Now from the python command line:
import y
dir(y)
['__builtins__', '__doc__', '__file__', '__name__', '__package__',
'x', 'y']
I do not understand why class 'x' shows up here.
Because that's how `import` behaves. It imports *every* member of the
module into the importing module's global namespace (except for
attributes that start with an underscore).

Um, no. (unless you do "from<whatever> import *" at the module level)

What it does is add whatever you imported into the namespace where you
imported it.

Because y.py has "from x import x" the x class from x.py is added to the
y.py namespace.

~Ethan~- Hide quoted text -

- Show quoted text -

So what is usually done to prevent this? (In my case not wanting class
x added to the y.py namespace)
It seems sloppy.

You can explicitly delete it at the end of the file if you never reference it
from one of your methods.

Mostly though, it just doesn't matter much. I recommend leaving it alone. If you
want a nice, clean namespace for people to use, make a module (e.g. api.py) that
doesn't define any classes or functions but just imports them from their
defining modules.

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

So what is usually done to prevent this? (In my case not wanting class x
added to the y.py namespace)
It seems sloppy.


(1) Don't import it in the first place.

(2) Import it with a different name, possibly private:

from module import x as _x

(3) Delete it when you're done:

from module import x
class Y(x):
pass
del x

(4) Don't be so fussy and just accept that importing adds names to the
namespace, as does any other assignment or class or function definition.
 
B

Brendan

(1) Don't import it in the first place.

(2) Import it with a different name, possibly private:

from module import x as _x

(3) Delete it when you're done:

from module import x
class Y(x):
    pass
del x

(4) Don't be so fussy and just accept that importing adds names to the
namespace, as does any other assignment or class or function definition.

I'll take (2) and pass on (4)
Thanks
 
D

Dave Angel

So what is usually done to prevent this? (In my case not wanting class
x added to the y.py namespace)
It seems sloppy.
Since you make the common mistake of using the same name for the module
as you do for the class, it's hard to demonstrate. But if you used Pep8
naming conventions, the classes would be capitalized.

Instead of using

from x import X

try using

import x

class Y(x.X):
pass

Now, you still have a symbol x in your namespace, but it's just the
module, which is perfectly public. So you could access a dozen classes
within x, but only the module itself would be visible to others.

As someone else pointed out, you could also delete the module reference
when you're done with it.

import x

class Y(x.X):
pass

del x


DaveA
 
B

Brendan

Since you make the common mistake of using the same name for the module
as you do for the class, it's hard to demonstrate.  But if you used Pep8
naming conventions, the classes would be capitalized.

Instead of using

from x import X

try using

import x

class Y(x.X):
     pass

Now, you still have a symbol x in your namespace, but it's just the
module, which is perfectly public.  So you could access a dozen classes
within x, but only the module itself would be visible to others.

As someone else pointed out, you could also delete the module reference
when you're done with it.

import x

class Y(x.X):
     pass

del x

DaveA

x.py
class X(object):
pass

y.py
import x
class Y(x.X):
pass

z.py
import x
import y
class ZX(x.X):
pass
class ZY(y.Y):
pass

w.py
import x
import y
import z
class WX(x.X):
pass
class WY(y.Y):
pass
class WZX(z.ZX):
pass
class WZY(z.ZY):
pass
['X', '__builtins__', '__doc__', '__file__', '__name__',
'__package__']['Y', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x']['ZX', 'ZY', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x', 'y']['WX', 'WY', 'WZX', 'WZY', '__builtins__', '__doc__', '__file__',
'__name__', '__package__', 'x', 'y', 'z']
 
P

Peter Pearson

On Fri, 22 Oct 2010 07:49:39 -0700 (PDT), Brendan wrote:
[snip]
x.py
class X(object):
pass

y.py
import x
class Y(x.X):
pass

z.py
import x
import y
class ZX(x.X):
pass
class ZY(y.Y):
pass

w.py
import x
import y
import z
class WX(x.X):
pass
class WY(y.Y):
pass
class WZX(z.ZX):
pass
class WZY(z.ZY):
pass
['X', '__builtins__', '__doc__', '__file__', '__name__',
'__package__']['Y', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x']['ZX', 'ZY', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x', 'y']['WX', 'WY', 'WZX', 'WZY', '__builtins__', '__doc__', '__file__',
'__name__', '__package__', 'x', 'y', 'z']

I apologize for being dense, but I don't understand what bothers
you about this behavior. Yes, module w imports x, and therefore
w.x exists. Is that bad?
 
B

Brendan

On Fri, 22 Oct 2010 07:49:39 -0700 (PDT), Brendan wrote:

[snip]




x.py
class X(object):
    pass
y.py
import x
class Y(x.X):
    pass
z.py
import x
import y
class ZX(x.X):
    pass
class ZY(y.Y):
    pass
w.py
import x
import y
import z
class WX(x.X):
    pass
class WY(y.Y):
    pass
class WZX(z.ZX):
    pass
class WZY(z.ZY):
    pass
import x, y, z, w
dir(x)
['X', '__builtins__', '__doc__', '__file__', '__name__',
'__package__']
['Y', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x']
['ZX', 'ZY', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', 'x', 'y']
['WX', 'WY', 'WZX', 'WZY', '__builtins__', '__doc__', '__file__',
'__name__', '__package__', 'x', 'y', 'z']

I apologize for being dense, but I don't understand what bothers
you about this behavior.  Yes, module w imports x, and therefore
w.x exists.  Is that bad?

No worries. I am the one who is dense. What bothers me is that I have
not noticed this before when importing other Python modules. I use
Python sporadically, and frequently use the dir command to learn or
remind myself of class methods. Python examples/tutorials on classes
always show everything(classes and subclasses) in the same module.
 
G

Gregory Ewing

Brendan said:
I use
Python sporadically, and frequently use the dir command to learn or
remind myself of class methods.

You can clean up dir() by defining __all__ as a list of
names that you want to officially export. Other names will
still be there, but they won't show up in the dir() listing.
 
P

Paul Rudin

Gregory Ewing said:
You can clean up dir() by defining __all__ as a list of
names that you want to officially export. Other names will
still be there, but they won't show up in the dir() listing.

I'm not sure that's necessarily a good idea... when you're trying to figure
out why something behaves in a certain way you want to check for the
presence of methods with special names.
 
L

Lawrence D'Oliveiro

Yes, module w imports x, and therefore w.x exists. Is that bad?

No-one seems to have come out and said this yet (unless it was in one of
those messages that no longer seem to be accessible on my ISP’s news
server): Python has no provision for visibility control. That’s it. No
public/private/protected or anything like that. Everything defined directly
within a module or class is visible outside it using dir(module_or_class).
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top