Friday, November 12, 2010

Python Namespace

So been brushing up on my limited Python-fu skill when I trip over the inexplicable namespace confusion (again).  Probably one of the few annoyances that trip newbie Pythonistas.

Ladies and Gents, I just came to a shocking realization.  I now know Python namespace!

Python namespace concept is actually quite simple - if you already have a programming background but can be nebulous if you dont.  This time though, I came equipped with some C language.

Namespace basically means that a variable and value's existence is context-dependent.  In Python, there are basically 3 to 4 possible namespace:
  1. Built in scope which basically means that variables (or names as it is called in Python) are global through out your program. If you program is spread out through different source file, built ins exist in each one of them file.
  2. Module scope which means that variable live through out your file and only this file.  You can call this variable from another file but you have to explicitly import it.
  3. Local scope are variables defined within a function or class method and this includes function arguments.
  4. Nested scope which is a variance of local scope.
So okay, point 1, 2, and even 4 is good, I get it.  It's the concept of local scope as applied to function parameters that was making me nuts.  I couldn't get it the first time.

Consider these 4 variables: s1 = 'this is a string' t1 = (1, 'one') l1 = [1, 'one'] d1 = {'name': 'gene'} Let's say you have a function that accept an argument ie. func1(arg1).  Normally, what would happen in other languages is that you get a copy of these variables as function parameters.  And this is what happens if you passed immutable objects such s1 (string) and t1 (tuple).  And that's how it should work.  The variable created in function either as a function argument or as regular variable declaration should only exist in that scope.  It's local!  But here, if you passed a mutable object (ie l1 and d1), you get direct access to their values rather than a copy of these values.

That's not how it's supposed to work... or is it?

And then it hit me!  Drum roll please!

It's all about pointers baby!  That's right, I'm so fucking glad I spent some time learning C before picking up Python again.

Okay, here goes as I understand it.

Consider the following assignment declaration in Python. place = 'Manila' number = 2010 city = place year = number Here what you have is the value 'Manila' and 2010. In Python, you can assign one or more names for these values. So in this case, both place/city and number/year have direct access these values.

In C, this would be equivalent into the following statement: char* place = 'Manila'; int* number = 2010; char* city = place; int* year = &number; (Note: There is no ampersand before the variable place because in char arrays, the first element of the array already indicate the initial address of these values.)

One caveat here is that in C, these values are mutable, so you would need to prefix the initial variable declaration with keyword const to make it immutable.

Once you associate C pointers with how Python local scoping work in function parameters then understanding how/why passing list and dictionary as arguments make these variables mutable and why it's not creating a copy.

Understanding how the following Python code work the way it does is now revealed to us.

colors = ['blue', 'red', 'green']
person = {'name': 'Gene', 'year': 2010 }
def change(c, p):
   c[0] = 'gold'
   p['year'] = 2011
Is similar to how C function implement a "call by reference".
typedef struct p { char name[10]; int year; }data;

void change (char** c, data* p)
{
c[0] = 'gold';
p->year = 2011;
}
main ()
{
char* colors[] = {"blue", "red", "green"};
data person = {"Gene", 2010};

change (colors, &person);
}
Passing dictionary and list as function argument is analogous to passing C arrays and pointers. That's why you can access and modify the original value of list and dictionary, because you can deference them with pointers or what you would technically refer to as "call by reference".

Yeah baby!!

No comments: