Python Concepts

    Indentation and Comments
    Methods
    "if" statements
    Data Structures
        Lists
        Tuples
        Dictionaries
    Classes
        Inheritance

Here is a simple piece of Python code to illustrate the basic features:
def myMethod(value1, value2):
    # This is a comment
 
    if value1 == 0:
        print "No value"
    elif value1 > 10:
        print "Value is greater than 10 "
    else:
        print "Value is ", value1

Indentation and Comments

Python recognizes code blocks by indentation. Because there are no brackets, you must make sure that statements within a code block all begin in the same column. Fortunately, the Python editor helps enforce this when you use the Tab key. Comments are denoted by the number sign: #

Methods

Python methods or functions are defined with the "def" keyword followed by method name, arguments, and a colon.

"if" statements

The format of an "if" statement with "elif" and "else" is shown above. Note that there are no parentheses around the expression which is instead followed by a colon.

Data Structures

Variables need not be declared or typed. They are defined as they are used. There are very powerful built-in data types.
  • Lists
  • A List is written as a list of comma-separated values (items) between square brackets. List items need not all have the same type. Lists are accessed via their index.

    Example:
     

        myList = ['spam', 'eggs', 100, 1234]
        myFavoriteFood = myList[0]
    A tuple consists of a number of values separated by commas, for instance:
        t = (12345, 54321, 'hello!')
        myNumber = t[0]
    They are indexed and referred to just as lists, but cannot be changed i.e. they are immutable.
    Another useful data type built into Python is the dictionary. Dictionaries are sometimes found in other languages as ``associative memories'' or ``associative arrays''. Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by keys, which can be any immutable type such as strings and numbers. Tuples can be used as keys if they contain only strings, numbers, or tuples. You cannot use lists as keys, since lists can be modified.
     
    It is best to think of a dictionary as an unordered set of "key:value" pairs, with the requirement that the keys are unique (within one dictionary). A pair of braces creates an empty dictionary: {}. Placing a comma-separated list of "key:value" pairs within the braces adds initial "key:value" pairs to the dictionary; this is also the way dictionaries are written on output. The main operations on a dictionary are storing a value with some key and extracting the value given the key. Here is an example using a dictionary:
     
        tel = {'jack': 4098, 'sape': 4139}
        tel['guido'] = 4127
        jacksNumber = tel[`jack']
        print tel
        print jacksNumber
    Result:
        {'guido': 4127, 'jack': 4098, 'sape':4139}
        4098
     

    Classes

    A "class" is a collection of methods and statementes that are related and perform a coherent set of tasks.  For example, if we have a set of methods that perform useful operations on strings, we might want to create a class structure to group them together.  A simple class can be declared as follows:

         class MyClass:                                # class declaration
              def myMethod(self, str):        # method defined within the class
                    print str                                # a simple print statement

    Notice the indentation.  Every method or variable within the class must be indented consistently to indicate its inclusion in the class.  Note the special "self" argument.  This is a way for us to keep track of what class a method or variable belongs to.  You don't need to worry much about it except to:

  • Make sure to list "self" as the first argument of method definitions within the class and
  • Make sure that when calling another method within the class, use "self.methodName" omitting  "self" as the first argument:
  •      class MyClass:
              def myMethod(self, str):
                    print str
              def anotherMethod(self):
                   self.myMethod("guido rocks")      class MyClass:

              def myMethod(self, str):
                    print str
                   self.myStr = str

              def anotherMethod(self):
                    self.myMethod("guido rocks")

             def aThirdMethod(self):
                   print "Last string printed", self.myStr

    When you want to use the methods inside a class, you "instantiate" the class or create an instance of the class.  Then you can call the methods of the class as shown below:

          classInstance = MyClass()
          classInstance.myMethod("spam and eggs")

    This would result in output of:

            spam and eggs

    Finally, you may want to include a "constructor" which is a special method to be run any time the class is instantiated.  This is handy if you want to initialize variables.

        class MyClass:
             def __init__(self):
                  self.myStr = ""

  • Inheritance
  • Often we find that a new class would benefit from having the functionality of an existing class.  Instead of altering the existing class, we can "inherit" its functionality and then add to it or alter it in our new class. For example,  suppose we have a WeatherElement class that stores and performs general operations on  a weather element such as temperature,  sky cover, or wind.    We might find operations for creating a new grid, storing a grid or deleting a grid from the inventory.  However, when we need to calculate the values for the grid, our functions might be different depending on whether the weather element is a Scalar or a Vector.  In this case, we might want to create two new classes, one for operating on Scalar weather elements and one for operating on Vector weather elements.  However, we would like both classes to have access to the general methods in the original WeatherElement class.

    When there is an inheritance relationship, we call the existing class the "base" class and the new class the "derived" class.  This relationship is specified as follows:

         class DerivedClass (BaseClass):
               def __init__(self):
                    BaseClass.__init__(self)

    Notice that we included a constructor and instantiated the BaseClass to ensure that any base class initializations will take place.   Here's how our example classes might be declared:

        class WeatherElement:
               def __init__(self):
                   pass
               def storeGrid(self):
                     ...
               def deleteGrid(self):
                    ...
               def createGrid(self):
                   ...

         class ScalarElement (WeatherElement):
               def __init__(self):
                    WeatherElement.__init__(self)
               def calculateScalarValues(self):
                     ...

         class VectorElement (WeatherElement):
               def __init__(self):
                    WeatherElement.__init__(self)
               def calculateVectorValues(self):
                     ...
               def createGrid(self):
                    # Special case of creating a vector grid
     

    Now the DerivedClass can call any methods in the BaseClass using the "self" argument.   So, for example, the "storeGrid" method is available to both the ScalarElement and VectorElement classes.  If we want to alter the functionality of a BaseClass method, we can simply include a copy of it in the DerivedClass definition and make any desired changes to it there.  Notice that we have included a copy of the "createGrid" method within the VectorElement class for which there will be some special set-up when creating the vector grid. When a method is called, the system first searches in the DerivedClass for it.  If it is not there, it searches in the BaseClass.  Of course, the BaseClass may have inherited from another class and, if so,  the search will proceed recursively.

    Sometimes it is useful to draw classes and their inheritance relationships.  We do so as shown below:


    The classes are represented by the rectangles and the special "inheritance symbol" indicates that the Derived Class inherits the methods and variables from the Base Class.  Think of the symbol not as an arrow indicating flow, but as an "umbrella" indicating inclusion of capabilities.