views:

51

answers:

1

Today one peculiar thing happened to me .I was trying to get a hang of appengine and djago on www.shell.appspot.com when i entered dir(django) the o/p i got was

['VERSION', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'conf', 'core', 'template', 'utils']

but still i tried

from django import forms

and it worked to my surprise , while there was no trances of this on the o/p of dir().so out of curiosity i again entered dir(django) and the o/p i got was

['VERSION', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'conf', 'core', 'forms', 'oldforms', 'template', 'utils']

note the forms element here .So can any one explain to me where this forms come from ?

+8  A: 

The statement from package import module loads (if it had not been previously loaded) package/module.py (after first loading package/__init__.py if it hadn't previously loaded it already) and adds 'module' as an entry in the package (as well as a variable in the current scope). So dir(package) will show a 'module' entry after the import, but not before.

A package can contain unbounded numbers of modules and subpackages (recursively) so it would be very slow to load everything in the package (just to fill out its dir!-) until specific modules and subpackages are specifically imported -- so, the loading of the latter is "just in time", when they're imported for the first time (and only then do they show up in the paren package's dir).

Alex Martelli
Looking at the forms module there are a ton of 'from module import *' statements which would also pull a lot of attributes into 'forms' namespace while it's being processed during import. Why aren't all of those variables included in the current scope recursively as well? Aren't imports supposed to load the files top-to bottom and include all of the dependencies when an import is called? Or is the tree of dependencies cached somewhere else and included in `__dict__` on-the-fly as they're called?
Evan Plaice
@Evan, "the attributes of an attribute of mine are **not** attributes of mine" -- why do you think they would be? Do you expect that if any `x` has an `x.y` which has an `x.y.z`, then automatically `x` must also have `x.z`? Or do you think that the entirely general rule I just mentioned has weird exceptions for packages and/or modules? it doesn't -- Python is very regular, exceptions and special cases are anathema to that! You **won't** see `'z'` in a `dir(x)` if the only way `z` is there is as `x.y.z` (or deeper).
Alex Martelli
@Alex maybe this isn't the best case to illustrate since forms is a submodule of django, so you'd still need to include the namespace to access its attributes (ex. forms.x). What if the case was, 'from django.forms import *' and the forms module contained the statement 'from x import xa, xb, xc'. Does that mean that `__dict__` should contain 'xa', 'xb', and 'xc'?
Evan Plaice
@Evan: if `django.forms` contains `from x import xa,xb,xc` and in your own code you do `from django.forms import *`, then yes you will wind up importing `xa`, `xb`, and `xc` - unless `django.forms` contains a module-level list variable named `__all__`, in which case your `from django.forms import *` would import only those variables whose _names_ are in `__all__`.
David Zaslavsky
@Evan, in your hypothetical case (net of `__all__` issues), `'xa'`, `'xb'` and `'xc'` would be in `dir(django.forms)` and in your importing namespace (so a `dir()` in that namespace would show them), but still **not** in `dir(django)` -- nothing put them there.
Alex Martelli
@Alex got it, thanks for clearing that up.
Evan Plaice
@All the reason i have been trying that was that i wanted to dig deeper in the django modules analyze the other submodules etc.So now the dir() rendered useless [in case i didn't knew there is a form mudule inside django how would have i come to know about it] what are the ways i can explore a module to discover its submodules/functions/classes.
Bunny Rabbit
@Bunny, I think "what are the ways i can explore a module to discover its submodules/functions/classes" is **well** worth a separate question (properly phrased with "a package" instead of "a module", and the contents are "modules, functions, classes and (recursively) subpackages") -- my A seems to entirely respond to this Q, and your new Q is really a completely different one (and big, too).
Alex Martelli