7

Reading the book "Introduction to computer science using Python", by Charles Dierbach, I got a question:

  • In page 210, he says "A reference is a value that references, or “points to,” the location of another entity. A variable’s reference value can be determined with built-in function id."

So a reference is just the address in memory of an object.

Now, if I'm not mistaken, when I create a variable like:

>>> a = 3

The name a is put automatically by Python in the namespace.

If I do:

>>> id(a)
4548344816

I get the address in memory of the object 3, the one that a is referencing.

So what I want to know is, how are the name a and the reference value related.

I'm guessing that when a name is a put into a namespace, it includes 2 things:

  1. The name itself.

  2. The reference value (id of the object)

A pair like maybe: a:reference value?

If so, is there some instrospection tool to see what an entry in the namespace look like?

Bobby Wan-Kenobi
  • 885
  • 9
  • 18

1 Answers1

5

Python namespaces are, on the whole, implemented as dictionaries. A key maps to a value, and in a namespace the keys are the identifiers, the names, and the values reference the objects that the names are tied to.

You already found the tool that makes the 'reference' part visible, the id() function. You can use the globals() and locals() functions to access the namespace mappings:

>>> a = 3
>>> globals().keys()
['__builtins__', '__name__', '__doc__', 'a', '__package__']
>>> globals()['a']
3
>>> id(globals()['a'])
4299183224
>>> id(a)
4299183224

Note however that in a function, the local namespace has been highly optimised and the dictionary returned by locals() is just a one-way reflection of the real structure, which is just a C array with references. You can look, but not touch, through this mapping.

If you wanted to further visualise how Python namespaces work, run your code in the Online Python Tutor; it'll show you how the names and Python objects in memory interact.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    Aha, I'm following another book of Mark Lutz, "Learning Python", and in pg . 176 he says *"variables and objects are stored in different parts of memory and are associated by links"*. I know I can get the address of the object with `id()`, but is there a way of finding out the address of the **name** itself? – Bobby Wan-Kenobi Feb 07 '15 at 14:15
  • 1
    Also, in the next page he says *"Variables are entries in a system table, with spaces for links to objects."* These entries he's referring to are the items of the namespace's dictionary. Every **item** in that dictionary works like a **link**, tying the name and the object. Right? – Bobby Wan-Kenobi Feb 07 '15 at 14:20
  • @javi: the book is being imprecise. Frame objects hold the namespaces, but both the frame objects *and* the name objects (which are just string objects) all live in the same memory space. – Martijn Pieters Feb 07 '15 at 14:36
  • 1
    @javi: so the names themselves are Python objects too; you can use `id()` on those, and again get a memory value. Or you can `id()` the dictionary `globals()` returns, that's just a reference to the actual dictionary used. – Martijn Pieters Feb 07 '15 at 14:39
  • @javi: finally, dictionaries are hash tables; you cannot further introspect that C hash table from Python. I talk a little about [how dictionaries work](http://stackoverflow.com/questions/15479928/why-is-the-order-in-python-dictionaries-and-sets-arbitrary/15479974#15479974), which includes more links to C implementation details. – Martijn Pieters Feb 07 '15 at 14:40
  • @Martjin: When I use `id()` on a name, I get the memory value of the object the name is referencing: `>>> id(a) == id(3)` and I get `True`. What I want to know, is it possible to get the memory address of the `name` itself. – Bobby Wan-Kenobi Feb 07 '15 at 14:46
  • @Martjin: The "system table" Mark Lutz is talking about is the dictionary we get with the `globals()` function, right? There's nothing more to it, yes? – Bobby Wan-Kenobi Feb 07 '15 at 14:48
  • @javi: the *keys* list in the dictionary gives you the string objects in that dictionary. So `globals().keys()` is a list, each element is a string object. `'a'` is one of these strings in that list. – Martijn Pieters Feb 07 '15 at 15:10
  • @javi: note that getting `id(a) == id(3)` as true is *an implementation detail*. The literal `3` in code could also have created a new object, but for small integers Python is reusing the same object over and over again because you create so many of them in almost all Python programs. – Martijn Pieters Feb 07 '15 at 15:11
  • @javi: the system table is indeed the dictionary `globals()` gives you. There are many such tables, one for each module. – Martijn Pieters Feb 07 '15 at 15:12