Imports, Namespaces, and References

References I had a decent idea of how importing and namespaces worked, but it wasn’t until I started setting up unit tests that everything clicked. False assumptions I had about namespaces and imports caused test failures. It forced me to do things the right way, so that I was changing the right objects instead of creating objects in random places. I learned how most things are references, and when you think of variables that way, namespaces and imports make a lot of sense.

Some basics

When you write a module, you start defining things: functions, variables, classes, etc.. When you define something, Python creates an object in memory. The variable name you use is how you refer to that chunk of memory. Everything is references behind the scenes.

A namespace is a container for these references. It maps variable names to addresses in memory. Any module you write has its own namespace. When you define variable mylist in your module, you are defining mylist in your module’s namespace. Variables defined in other modules, or I should say in other modules’ namespaces, are not accessible in your module – unless you import them.

You will work with open source libraries, and to unlock their power you need to access their functions and classes which are in the library’s namespace. You gain access though importing. At a high level Python imports modules by doing the following:

  1. See if the module name is in sys.modules – this like a cache of imported modules.
  2. If not, look for the file that matches the module name
  3. Run the module being imported. This setups up all global variables, including variables for classes & functions
  4. Put the loaded module into sys.modules
  5. Setup references so you can access imports – where the fun happens.

I want to explain these in a little more detail as well as how they affect modifying variables inside of an import. I will go through the steps out of order because step 1, loading from the cache, doesn’t mean much except after step 4, putting a module into the cache.

Step 2: Finding what to import

Finding the modules is pretty useful and interesting, but does not have a lot to do with references so I am skipping the details here. Also, the Python docs outline this clearly and succulently:

https://docs.python.org/3.3/tutorial/modules.html#the-module-search-path

Step 3: Executing Code

After finding the file, Python loads and executes it. To give a concrete example, I have 2 simple modules:

cars.py

car_list = [1]

def myfun():
    return car_list

print "Importing..."

dealer.py

import cars

If you run cardealer.py, you see the following:

> python cardealer.py
Importing...

So by loading and executing I mean Python runs everything at the top level. That includes setting variables, defining functions, and running any other code, such as the print statement in cars.

It also does this in each module’s own namespace. Defining car_list in cars basically adds a pointer in cars to this new list. It does not affect dealer, which could have its own, completely independent variable named car_list. After the import is done, dealer will also not have direct access to car_list. cars has the reference/pointer to that object in memory, and the only way dealer can access the list is to go through cars: cars.car_list.

Step 4 & Step 1

Caching takes place after loading the module. Python stores the module in a module class object, which it puts into the sys.modules dictionary. The key is usually the name of the module, with 1 exception. If the module is the the one you are directly running, its key is ‘main‘. (Aside: this is why we use if name == ‘main‘).

What’s cool is that you can access modules through sys.modules. So back to the simple module. After importing it, you can access the list as cars.car_list. You can also access it through sys.modules:

>>> import sys
>>> sys.modules['cars'].car_list
[1]

The caching in sys.modules has many effects. Importing a cached module means it doesn’t get executed again. Reimporting something is cheap! It also means that all the classes, functions, and variables defined at the top level are only defined once, and statements only execute once. The print statement in cars won’t print if it is imported again, or imported anywhere else in the same process.

Step 5: Reference Setup

This is where the most interesting stuff happens. Depending on how you import something, references are setup in your module’s namespace to let you access what you imported. There are a few variations, and I have some code that shows what Python effectively does. Remember, the modules are already loaded into sys.modules at this point.

  1. import cars

    cars= sys.modules['cars']
  2. import cars as vehicles

    vehicles= sys.modules['cars']
  3. from cars import car_list

    car_list = sys.modules['cars'].car_list

No matter how you import something, code from a module always runs in its own namespace. So when cars looks up a variable, it looks it up in cars’s own namespace, not who imported.

Mutability

Imported variables behave is the same way as regular variables, which depends on mutability.

Remember, when Python creates an object, it puts it somewhere in memory. For mutable objects (dict, list, most other objects), when you make a change to that object, you change the value in memory. For immutable objects (int, float, str, tuple), you can never change the value in memory. For immutable objects you can reassign the variable to point to a new value, but you cannot change the original value in memory.

To illustrate this I can use the id function which prints an address in memory for a variable. I modify the value of an int and a list.

Immutable:

>>> a = 1
>>> id(a)
140619792058920
>>> a += 1
>>> id(a)
140619792058896

Mutable

>>> b = [1]
>>> id(b)
4444200832
>>> b += [2]
>>> id(b)
4444200832

When I change the value of a, the immutable integer, the id changes. But when I do the same for a list, the id remains the same.

There is a sneaky catch though! Many times when you assign a variable, even a mutable one, you change the reference.

>>> b = [1]
>>> id(b)
4320637944
>>> b = b + [2]
>>> id(b)
4320647936

Behind the scene, Python is creating a new list, and changing where the b reference is pointing. The difference can be subtle between this case and the += case above. I wouldn’t worry about it much, it’s never affected me, but it’s good to be aware.

Modifying Imports

So how can I change values in imported modules? And how does mutability affect imports?

The way you access, and sometimes change, variables in imported modules may, or may not, have an effect on the module. This is where unit tests taught me a lot, since my tests imported modules and tried to set variables in order to setup certain test cases. I learned it all comes down to references. There are a few key rules.

Modules execute their code in their own namespace

When a function in cars tries to use car_list, it looks up car_list in cars namespace. That means:

The module is only affected if:

  • you update the object data behind that reference, or
  • **you change where the reference points in the module’s namespace **

There are some simple ways to update what’s behind the reference – which works no matter how you import. Let’s run this code:

tester_1.py

import cars
from cars import car_list, myfun
# update data through the cars module
cars.car_list.append(2)
print "updated through cars:", cars.myfun()
# update through my namespace
car_list.append(3)
print "updated imported var:", myfun()

This outputs:

> python tester_1.py
Importing...
updated through cars: [1, 2]
updated imported var: [1, 2, 3]

It’s trickier to change cars’s reference, which does depends on how you import:

tester_2.py

import cars
from cars import car_list, myfun
# change referece through the cars module
cars.car_list = [2]
print "changed cars reference    :", cars.myfun()
# the imported variable still points to the original value
print "test original import      :", cars_list
# changing the imported variable will not affect the "real" value
# so this should print the same as the first call
car_list = [3]
print "changed imported reference:", myfun()

This outputs:

> python tester_2.py
changed cars reference    : [2]
test original import      : [1]
changed imported reference: [2]

In both cases, we are creating a new list, and changing what the variables are referencing. But remember, myfun is in cars, and gets variables from the cars namespace. In the first case we are going to the cars namespace, and setting its car_list to this new list. When myfun runs, it gets the reference we just updated and returns our new list.

When we from cars import car_list we create a car_list in the tester_2 namespace which points to the same list cars has. When cars’s reference is set to [2], tester_2′s reference stays unchanged, which is why it keeps the value [1]. When we update car_list in tester_2′s namespace, it only changes where tester_2 is pointing. It is not changing where cars points (and not changing the value in memory where cars points), so it has no effect on how the cars module runs. So when we check myfun, it returns [2].

Final thoughts

When you run into a problem where you set a variable in one module, then access it though another, knowing what’s going on behind the scenes helps make sense of it all. With imports it’s easy to figure out what’s going on when you realize that variables are pointers to objects in memory. If your code is not doing what you expect when setting variables, then something is pointing to the wrong object. Knowing how Python works behind the scenes with namespaces and imports will help you figure out what’s going on. It’s really not bad once you realize it’s all just references.

Using Angular Rapydly

RapydScript with AngularJS I’ve been asked a few times if RapydScript works with Angular. The answer is the same as with any other JavaScript framework/library/etc. – of course! RapydScript takes the same approach to compilation/abstraction as CoffeeScript, so there really isn’t anything JavaScript can do that RapydScript can’t. Salvatore has already proven this with multiple demos using frameworks I haven’t even thought of. I urge any developer with similar questions to just try it out, it’s easier (and more fun) to spend an hour building an app than hesitating about it for weeks.

With that said, I decided to put together this tutorial by cloning the 5 examples shown here via RapydScript. I suggest you read the original article before this post. I should also mention that I myself have not used AngularJS before, and decided to learn it through these examples as well. I was a bit disappointed to see that a big chunk of AngularJS is handled magically from their html templates rather than JavaScript itself. This means that there is very little actual JavaScript (and hence RapydScript) used. As far as html itself, you could either write it directly, or use RapydML or Jade (both will have similar syntax). For the purposes of this post, I will leave css code alone, although you can easily convert it to sass as well. Let’s get started.

Setup (Only Needed for RapydML)

Looking at the first example, we immediately notice Django-like variables in the html code. That’s a sign that we may want to use template engines in RapydML. So let’s slap one together. Glancing through the examples we see that most AngularJS variables follow this format:

{{var}}

Doesn’t look like they’re doing anything fancy, so let’s create a very simple template engine in a new pyml file:

angular = TemplateEngine('{%s}')
angular.js = create('{%s}')

I should also mention that you can use AngularJS from RapydML directly, without creating a template engine, I chose to do so for clarity. But nothing prevents you from writing this:

div:
    'This is an angular var: {{myvar}}'

Example 1 (Navigation Menu)

This one doesn’t require any JavaScript. We’ll just need to slap together a RapydML template, leveraging the 2-line template engine we just wrote:

import angular

div(id="main", ng-app):
    nav(class="angular.js(active)", ng-click="\$event.preventDefault()"):
        for $name in [home, projects, services, contact]:
            a(href='#', class="$name", ng-click="active='$name'"):
                python.str.title('$name')

    p(ng-hide='active'):
        'Please click a menu item'
    p(ng-show='active'):
        'You choose'
        b:
            "angular.js(active)"

That’s it, compile it and plug into AngularJS. You will need the most recent version of RapydML, older versions did not handle template engine calls within strings, the new one handles them in double-quoted strings and ignores them in single-quoted strings.

Example 2 (Inline Editor)

As before, we start with the RapydML code:

import angular

div(id='main', ng-app, ng-controller='InlineEditorController', ng-click='hideTooltip()'):
    div(class='tooltip', ng-click='\$event.stopPropagation()', ng-show='showtooltip'):
        input(type='text', ng-model='value')
    p(ng-click='toggleTooltip(\$event)'):
        "angular.js(value)"

Next, let’s add some RapydScript:

def InlineEditorController($scope):
    $scope.showtooltip = False
    $scope.value = 'Edit me.'

    $scope.hideTooltip = def():
        $scope.showtooltip = False

    $scope.toggleTooltip = def(e):
        e.stopPropagation()
        $scope.showtooltip = not $scope.showtooltip

Once again, after compiling the first block of code via RapydML and second via RapydScript, we’ll have a fully-working example.

Example 3 (Order Form)

In this example, we see a new way of hooking into AngularJS. Note the {active: service.active} class tag. We could either reference is in the code verbatim (since it is quoted), or add a new method to the angular template engine for consistency:

angular.active = create('active: %s')

We can now continue with the 3rd example, first the RapydML code:

import angular

form(ng-app, ng-controller='OrderFormController'):
    h1:
        'Services'
    ul:
        li(ng-repeat='service in services', ng-click='toggleActive(service)', ng-class="angular.active(service.active)")
        "angular.js(service.name)"
        span:
            "angular.js(service.price | currency)"

    div(class='total'):
        'Total: '
        span:
            "angular.js(total() | currency)"

Finally, let’s complement it with RapydScript:

def OrderFormController($scope):
    $scope.services = [
        {
            name: 'Web Development',
            price: 300,
            active: True
        }, {
            name: 'Design',
            price: 400,
            active: False
        }, {
            name: 'Integration',
            price: 250,
            active: False
        }, {
            name: 'Training',
            price: 220,
            active: False
        }
    ]

    $scope.toggleActive = def(s):
        s.active = not s.active

    $scope.total = def():
        total = 0
        angular.forEach($scope,services, def(s):
            nonlocal total
            if s.active:
                total += s.price
        )
        return total

As usual, looks similar to the JavaScript version. RapydScript did prevent us from shooting ourselves in the foot by accidentally declaring total as global, something you’d need to be careful about in native JavaScript version.

Example 4 (Instant Search)

For this example, I’ll actually show alternative RapydML code, that doesn’t use our template engine:

div(ng-app='instantSearch', ng-controller='InstantSearchController'):
    div(class='bar'):
        input(type='text', ng-model='searchString', placeholder='Enter your search terms')

    ul:
        li(ng-repeat='i in items | searchFor:searchString')
            a(href='{{i.url}}'):
                img(ng-src='{{i.image}}')
            p:
                '{{i.title}}'

That was even easier than the template engine version, I think I’ll stick to this for my next example as well. Now the RapydScript portion:

app = angular.module('instantSearch', [])
app.filter('searchFor', def():
    return def(arr, searchString):
        if not searchString:
            return arr

        result = []
        searchString = searchString.toLowerCase()
        angular.forEach(arr, def(item):
            if item.title.toLowerCase().indexOf(searchString) != -1:
                result.push(item)
        )
        return result
)

def InstantSearchController($scope):
    $scope.items = [
        {
            url: 'http://tutorialzine.com/2013/07/50-must-have-plugins-for-extending-twitter-bootstrap/',
            title: '50 Must-have plugins for extending Twitter Bootstrap',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/07/featured_4-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/08/simple-registration-system-php-mysql/',
            title: 'Making a Super Simple Registration System With PHP and MySQL',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/simple_registration_system-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/08/slideout-footer-css/',
            title: 'Create a slide-out footer with this neat z-index trick',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/08/slide-out-footer-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/06/digital-clock/',
            title: 'How to Make a Digital Clock with jQuery and CSS3',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/06/digital_clock-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/05/diagonal-fade-gallery/',
            title: 'Smooth Diagonal Fade Gallery with CSS3 Transitions',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/featured-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/',
            title: 'Mini AJAX File Upload Form',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/05/ajax-file-upload-form-100x100.jpg'
        }, {
            url: 'http://tutorialzine.com/2013/04/services-chooser-backbone-js/',
            title: 'Your First Backbone.js App – Service Chooser',
            image: 'http://cdn.tutorialzine.com/wp-content/uploads/2013/04/service_chooser_form-100x100.jpg'
        }
    ]

On to the last example.

Example 5 (Switchable Grid)

First the RapydML code, as usual:

def layout($type, $imgtype):
    ul(ng-show="layout == '$type'", class="$type"):
        li(ng-repeat='p in pics'):
            a(href='{{p.link}}', target='_blank'):
                img(ng-src="{{p.images.$imgtype.url}}")

div(ng-app='switchableGrid', ng-controller='SwitchableGridController'):
    div(class='bar'):
        for $icon in [list, grid]:
            a(class='$icon-icon', ng-class="{active: layout == '$icon'}", ng-click="layout = '$icon'")
    layout(list, low_resolution)
    layout(grid, thumbnail)
            p:
                '{{p.caption.text}}'

Notice that I chose to be a little more DRY and create an extra function, you don’t have to do that if you believe it hurts readability. Next, the RapydScript code:

app = angular.module('switchableGrid', ['ngResource'])
app.factory('instagram', def($resource):
    return {
        fetchPopular: def(callback):
            api = $resource('https://api.instagram.com/v1/media/popular?client_id=:client_id&callback=JSON_CALLBACK', {
                client_id: '642176ece1e7445e99244cec26f4de1f'
            }, {
                fetch: { method: 'JSONP' }
            })

            api.fetch(def(response):
                callback(response.data)
            )
    }
)

def SwitchableGridController($scope, instagram):
    $scope.layout = 'grid'
    $scope.pics = []
    instagram.fetchPopular(def(data):
        $scope.pics = data
    )

Conclusion

While the RapydScript code above might be a bit cleaner than the original JavaScript code, it’s hard to argue that significant value was gained from porting it. The main benefit of RapydScript comes into play when building larger-scale applications that leverage classes and use numerous variables. Such code increases the chances of shooting yourself in the foot or getting confused when dealing with native JavaScript. Indeed, if you look at some of the jQuery plugins, you’ll see that the code itself seems unmaintainable. After a few layers of anonymous functions it’s hard to figure out what’s being passed around where. AngularJS keeps the code short by handling a lot of the logic for you on the background, RapydScript allows you to keep your own logic readable as it grows. No matter how awesome a framework is, eventually you’ll be writing a lot of your own logic as well.