Python Primer

This section will provide a short introduction to namespaces in Scorpion and Python. These concepts are important for everybody who wants to exploit the power of Python in Scorpion.

Variables and namespaces

All variables in Python, and every other programming language, are created and exist in a namespace. What is a namespace?

Using PythonWin, an integral part for Python Extension for Windows, or Idle - yet another Python environment, one can play with namespaces.

An assignment is a statement of type a=b where a is a variable and b another variable, constant, constructor or function.

a=100
b=1.03
c=’spam’
e=[]
f={}
g=eggs()

are assignments where:

a is assigned an integer value,
b a floating point value,
c a string
e an empty list
f an empty dictionary
g the value of function or a reference to an instance of a class

When Python is initialized, a namespace is created. It is available for declaration of variables, functions and objects.

Declarations:

a=100

def foo(b):
  print ‘a=’,a,’b=’,b

The statement:

foo(200)

Will yield the output:

a=100 b=200

Python searches for a local definition of a in foo(). If not found Python search in the global namespace. If a local variable is defined in foo() the result will be as follows:

Declarations:

a=100

def foo(b):
  a=300
  print ‘a=’,a,’b=’,b

The statement:

foo(200)

Will yield the output:

a=300 b=200

The statement:

print ‘a=’,a

Will yield the output:

a=100

Functions and name spaces can be nested:

a=100

def foo(b):
  a=300

   def spam(b):
    a=400
    print ‘a=’,a,’b=’,b
    spam(500)
      print ‘a=’,a,’b=’,b

The statement:

foo(200)

Will yield the output

a=400 b=500
a=300 200

The statement:

print ‘a=’,a

Will yield the output:

a=100

Lets modify this slightly:

a=100
def foo(b):

  def spam(b):
    print ‘a=’,a,’b=’,b

  spam(500)
  print ‘a=’,a,’b=’,b

The statement:

foo(200)

Will yield the output:

a=100 b=500
a=100 b=200

The statement:

print ‘a=’,a

Will yield the output:

a=100

Python finds the value of a by searching in the nested namespaces. To change a global variable we can instruct Python to do so.

a=100
def foo(b):

  def spam(b):
    global a
    a=b
    print ‘a=’,a,’b=’,b

  spam(500)
  print ‘a=’,a,’b=’,b

The statement:

foo(200)

Will yield the output:

a=500 b=500
a=500 b=200

The statement:

print ‘a=’,a

Will yield the output:

a=500

A Script - An ordered collection of statements

A script is an ordered collection of Python statements. Scripts are stored in a text format. This can be a file. The file is given the .py extension and is called a module. It can also be named a Script. To get access to the variable, classes and functions we use the import directive.

When loading the module all definitions and assignments are executed. Functions, classes and variables must be imported to get into scope. The module cannot access methods and functions defined outside the module unless the import statement is used.

How do we access the content of a module?

We create a module named OneModule.py with content:

a='One Module'

z='Another Module'

def foo(c):
  print 'What happens next?'

Lets store the module in the directory c:\PythonPrimer. This is a directory Pyhton does not know. It can be added to the Python system path with the following statements:

import sys
sys.path.append(’c:\\pythonprimer’)

sys is a standard module in Python. path is a property in the sys module. More information about sys and path is found in the Python Help file.

Qualified Import

import OneModule

a = 100
print a
100
print OneModule.a

’OneModule’

We see that the two a variable are in different name spaces. We get access to OneModule.a using dot notation.

Unqualified Import

What happens if we import OneModule using the import * syntax?

from OneModul import *

print a

’One Module’

The global variable a is assigned by the OneModule script. Calling foo() will show that foo() is redefined or destroyed?

foo(100)

’What happens next?’

Unqualified import can be dangerous - it will redefine functions and possibly overwrite variables when names are identical.

Hint: Use qualified import to avoid accidents

Classes have their own namespaces

A way to protect your functions and variables is to use a class to create a protected name space. Another benefit is that one can create multiple instances of the class - which is a powerful feature making life easier and more fun for a lazy programmer (lazy programmers = efficient programmers).

We create another module AnotherModule.py. Then define a class named ASimpleClass and store it in C:\PythonPrimer

class ASimpleClass:
  def __init__(self):
    self.a=’A  Simple Class’

  def foo(self,b):
     print ‘a=’,self.a,‘b=’,b

Statements and output:

from AnotherModule import *

m=ASimpleClass()
print m. a
’A Simple Class’
m.foo(’spam’’)
a=’A  Simple Class’ b=’spam’
m.a=a
print m.a
a=100

You can protect variables using a class definition this way:

class Glob:
    a=100

glob=Glob()

print glob.a

100

glob.b=200

print glob.b

200

As you can see you can add new variables to the class - on the fly! - and get the protection and scoping you need.

Python and Scorpion

Python is integrated in Scorpion. You may write Python code in:

Tools
Central
Central.Start
Central.Stop
Central.Scripts

Central.Start is the starting point for all Python execution within Scorpion.

Central.Start is run by Scorpion during startup which means that this is THE place to put global declarations of classes, functions and variables. Anything declared within Central.Start is available to PythonTools and Central.Scripts.

Good programming practice in Scorpion:

  1. Declare all variables, functions and classes that are ment to be global in Central.Start
  2. Use the global directive in all scripts referring to global variables, even though if the variables are only ReadOnly. Tell yourself and any other user of your profile that you know exactly what you are doing.
  3. Any variable declared in a PythonTool should be regarded as local to this script. They will become global after the first assignment - but this is bad practice.
  4. Do not import your own modules with the from module import * statement if the module contains global assignments. The consequence is that previous declared global vaiables with equal names will be overwritten. Use the import statement instead.
  5. Try rewriting modules containing variables and functions into classes.