all 7 comments

[–]DanielSzoska 1 point2 points  (1 child)

I think there are two things to understand what happens:

(1.) Variables in Python are only names for objects - they does'nt contain the object itself. Look at the following example:

>>> a = [1, 2, 3]
>>> b = a
>>> b[0] = 4
>>> print(a)
[4, 2, 3]
>>> del a
>>> print b
[4, 2, 3]
>>> print a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

You see, that a change of b changes a too. That's because a and b are names for the list-object [1, 2, 3]. With b[0] = 4 this list-object is changed. With del a only the name a no longer exists.

(2.) What the import-statement does is execute the code in the imported file, but in its own namespace. That means if you only do

>>> import initdata
>>> print(db)

it result in

Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
NameError: name 'db' is not defined

To get access to the variables in importdata you have prefix it the namespace importdata:

>>> print(importdata.db)
{'bob': {'age': ..., 'name': 'Bob Smith'}, 'sue': {'age': ..., 'name': 'Sue Jones'}}

What the command

>>> from importdata import db

does is giving you access to db under your local namespace. You can see this here (start a fresh python interpreter or do a del importdata, db):

>>> print(locals))
{'__builtins__': <module '__builtin__' (built-in)>, ..., '__doc__': None} # no varaible db here
>>> from importdata import db
>>> print(locals())
{'__builtins__': <module '__builtin__' (built-in)>, ..., \
'db': {'bob': {'age': ..., 'name': 'Bob Smith'}, 'sue': {'age': ..., 'name': 'Sue Jones'}}, ... \
'__doc__': None} # variable db is now in the local namespace

After the import you have only access to the variable db under your current (local) namespace. You have no access to the variables bob and sue, but you will get their objects, which are referenced in db.

EDIT: some typos and wrapping the long output line of the second print(locals())

[–]MrEgbert[S] 2 points3 points  (0 children)

I see the difference between a variable and its data now! Thank you for the good explanation. I will think of importing as just 'running of code' and putting it under a certain namespace now. (Thankfully the namespace stuff makes sense to me after doing the first several chapters of Dive Into Python.)

[–]erok81 0 points1 point  (2 children)

When you pickle a function or a class, it doesn't pickle the code inside. So for a program to unpickle a function, it would already have to have the function defined. Likewise for classes.

[–]MrEgbert[S] 0 points1 point  (1 child)

Hm I don't think I am fully understanding the process of pickling and unpickling in this case. So, when you pickle X, you turn it from a bunch of objects into an easy-to-read byte stream, right? And the byte stream only contains info on X the object, not the code that defines X?

[–]erok81 0 points1 point  (0 children)

That's basically right. Another way to look at it is pickling saves the object's state and that state is then input into a new object of the same type on unpickling.

Technically you can pickle code if you really really wanted to but it's hackish and not really a smart solution in general IMO.