Python 101 - Introduction to Python - Part 3

by Dave Kuhlman
Rexx.com
Wednesday, 3rd August 2005

Organization

This section describes Python features that you can use to organize and structure your code.

Functions

A basic function

Use def to define a function. Here is a simple example:

 

def test(msg, count):
for idx in range(count):
print '%s %d' % (msg, idx)

test('Test #', 4)

Comments:

 

  • After evaluation def creates a function object.

     

  • Call the function using the parentheses function call notation, in this case "test('Test #', 4)".

     

  • As with other Python objects, you can stuff a function object into other structures such as tuples, lists, and dictionaries. Here is an example:

     

    # Create a tuple:
        val = (test, 'A label:', 5)
       
        # Call the function:
        val[0](val[1], val[2])

A function with default arguments


Providing default arguments allows the caller to omit some arguments. Here is an example:

 

def testDefaultArgs(arg1='default1', arg2='default2'):
print 'arg1:', arg1
print 'arg2:', arg2

testDefaultArgs('Explicit value')

The above example prints:

 

arg1: Explicit value
arg2: default2

Argument lists and keyword argument lists

Here is an example:

 

def testArgLists_1(*args, **kwargs):
print 'args:', args
print 'kwargs:', kwargs

testArgLists_1('aaa', 'bbb', arg1='ccc', arg2='ddd')

def testArgLists_2(arg0, *args, **kwargs):
print 'arg0: "%s"' % arg0
print 'args:', args
print 'kwargs:', kwargs

print '=' * 40
testArgLists_2('a first argument', 'aaa', 'bbb', arg1='ccc', arg2='ddd')

Running this example displays:

 

args: ('aaa', 'bbb')
kwargs: {'arg1': 'ccc', 'arg2': 'ddd'}
========================================
arg0: "a first argument"
args: ('aaa', 'bbb')
kwargs: {'arg1': 'ccc', 'arg2': 'ddd'}

A little guidance:

 

  • Positional arguments must proceed all keyword arguments when you call the function.

     

  • You can also have "normal" arguments in the function definition. For example: "def test(arg0, *args, **kwargs):". See the second example above.

     

  • The keyword argument parameter is a dictionary, so you can do anything with it that you do with a normal dictionary.

Classes and Instances

A basic class

Define a basic class as follows:

 

class Basic:
def __init__(self, name):
self.name = name
def show(self):
print 'Basic -- name: %s' % self.name

obj1 = Basic('Apricot')
obj1.show()

Running the above example produces the following:

 

Basic -- name: Apricot

Explanation:

 

  • Methods are added to the class with def. The first argument to a method is the class instance. By convention it is spelled "self".

     

  • The constructor for a class is a method named "__init__".

     

  • The self variable must be explicitly listed as the first argument to a method. You could spell it differently from "self", but don't do so.

     

  • Instance variables are referred to with "self.XXX". Notice how in our example an argument to the constructor is saved as an instance variable.

     

  • An instance is created by calling the class. For example: "obj = Basic('Apricot')".

     

  • In addition to __init__ there are other special method names of the form "__XXX__", which are used to customize classes and their instances. These are described at http://www.python.org/doc/current/ref/specialnames.html.

     

A few more notes on self:

 

  • self is a reference to the instance. Think of it (in part) as a reference to the container for the data or state for the object.

     

  • In many object-oriented programming languages, the instance is hidden in the method definitions. These languages typically explain this by saying something like ``The instance is passed as an implicit first argument to the method.''

     

  • In Python, the instance is visible and explicit in method definitions. You must explicitly declare the instance as the first parameter of each (instance) method. This first parameter is (almost) always spelled ``self''.

Inheritance

Define a class Special that inherits from a super-class Basic as follows:

 

class Basic:
def __init__(self, name):
self.name = name
def show(self):
print 'Basic -- name: %s' % self.name

class Special(Basic):
def __init__(self, name, edible):
Basic.__init__(self, name)
self.upper = name.upper()
self.edible = edible
def show(self):
Basic.show(self)
print 'Special -- upper name: %s.' % self.upper,
if self.edible:
print "It's edible."
else:
print "It's not edible."
def edible(self):
return self.edible

obj1 = Basic('Apricot')
obj1.show()
print '=' * 30
obj2 = Special('Peach', 1)
obj2.show()

Running this example produces the following:

 

Basic -- name: Apricot
==============================
Basic -- name: Peach
Special -- upper name: PEACH. It's edible.

Commentary:

 

  • The super-class is named after the class name in parentheses. For multiple inheritence, separate the super-classes with commas.

     

  • Call a method in the super-class, by-passing the method with the same name in the sub-class, from the sub-class by using the super-class name. For example: "Basic.__init__(self, name)"and "Basic.show(self)".

     

  • In our example (above), the sub-class (Special) specializes the super-class (Basic) by adding additional member variables (self.upper and self.edible) and by adding an additional method (edible).

Class data

A class data member is a member that has only one value for the class and all its instances. Here is an example from the Python FAQ at http://www.python.org/doc/FAQ.html:

 

class C:
count = 0 # number of times C.__init__ called
def __init__(self):
C.count = C.count + 1
def getcount(self):
return C.count # or return self.count

c1 = C()
print 'Current count:', c1.getcount()
c2 = C()
print 'Current count:', c2.getcount()

Running this example produces:

 

Current count: 1
Current count: 2

Static Methods and class methods

Here is an example that shows how to define static methods and class methods:

 

class Advanced:
def __init__(self, name):
self.name = name
def Description():
return 'This is an advanced class.'
def ClassDescription(cls):
return 'This is advanced class: %s' % repr(cls)
Description = staticmethod(Description)
ClassDescription = classmethod(ClassDescription)

obj1 = Advanced('Nectarine')
print obj1.Description()
print obj1.ClassDescription()
print '=' * 30
print Advanced.Description()
print Advanced.ClassDescription()

Running the above produces the following output:

 

This is an advanced class.
This is advanced class: <class __main__.Advanced at 0x401c926c>
==============================
This is an advanced class.
This is advanced class: <class __main__.Advanced at 0x401c926c>

Notes:

 

  • Create a static method with "x = staticmethod(y)", where y is a normal method but without the self/first parameter.

     

  • Create a class method with "x = classmethod(y)", where y is a normal method.

     

  • The difference between static and class methods is that a class method receives the class (not the instance) as its first argument.

     

  • You can call static and class methods using either an instance or a class. In our example either "obj1.Description()" or "Advanced.Description()" will work.

     

You should also review the relevant standard Python documentation which you can find at Python Library Reference - 2.1 Built-in Functions.

By now, you are likely to be asking: ``Why and when should I use class methods and static methods?'' Here is a bit of guidance, though

 

  • Most of the time, almost always, implement plain instance methods. Implement an instance method whenever the method needs access to the values that are specific to the instance or needs to call other methods that have access to instance specific values. If the method needs self, then you probably need an instance method.

     

  • Implement a class method (1) when the method does not need access to instance variables and (2) when you do not want to require the caller of the method to create an instance and (3) when the method needs access to class variables. A class method may be called on either an instance or the class. A class method gets the class as a first argument, whether it is called on the class or the instance. If the method needs access to the class but does not need self, then think class method.

     

  • Implement a static method if you merely want to put the code of the method within the scope of the class, perhaps for purposes of organizing your code, but the method needs access to neither class nor instance variables (though you can access class variables through the class itself). A static method may be called on either an instance or the class. A static method gets neither the class nor the instance as an argument.

     

To summarize:

 

  • Implement an instance method, unless ...

     

  • ... the method needs access to class variables but not instance variables, then implement a class method, unless ...

     

  • ... the method needs access to neither instance variables nor class variables and you still want to include it within the class definition, then implement a static method.

     

  • Above all, write clear, plain code that will be understandable to your readers. Do not use a more confusing language feature and do not force your readers to learn a new language feature unles you have a good reason.

Modules

You can use a module to organize a number of Python definitions in a single file. Here is an example:

 

# python_101_module_simple.py

"""
This simple module contains definitions of a class and several
functions.
"""

LABEL = '===== Testing a simple module ====='

class Person:
"""Sample of a simple class definition.
"""
def __init__(self, name, description):
self.name = name
self.description = description
def show(self):
print 'Person -- name: %s description: %s' % (self.name, self.description)

def test(msg, count):
"""A sample of a simple function.
"""
for idx in range(count):
print '%s %d' % (msg, idx)

def testDefaultArgs(arg1='default1', arg2='default2'):
"""A function with default arguments.
"""
print 'arg1:', arg1
print 'arg2:', arg2

def testArgLists(*args, **kwargs):
"""
A function which references the argument list and keyword arguments.
"""
print 'args:', args
print 'kwargs:', kwargs

def main():
"""
A test harness for this module.
"""
print LABEL
person = Person('Herman', 'A cute guy')
person.show()
print '=' * 30
test('Test #', 4)
print '=' * 30
testDefaultArgs('Explicit value')
print '=' * 30
testArgLists('aaa', 'bbb', arg1='ccc', arg2='ddd')

if __name__ == '__main__':
main()

Running the above produces the following output:

 

===== Testing a simple module =====
Person -- name: Herman description: A cute guy
==============================
Test # 0
Test # 1
Test # 2
Test # 3
==============================
arg1: Explicit value
arg2: default2
==============================
args: ('aaa', 'bbb')
kwargs: {'arg1': 'ccc', 'arg2': 'ddd'}

Comments:

 

  • The string definitions at the beginning of each of the module, class definitions, and function definitions serve as documentation for these items. You can show this documentation with the following from the command-line:

     

    $ pydoc python_101_module_simple

    Or this, from the Python interactive prompt:

     

    >>> import python_101_module_simple
    >>> help(python_101_module_simple)

     

  • It is common and it is a good practice to include a test harness for the module at the end of the source file. Note that the test "if __name__ == '__main__':" will be true only when the file is run (e.g. from the command-line with "$ python python_101_module_simple.py"), but not when the module is imported.

     

  • Remember that the code in module is only evaluated the first time it is imported in a program. So, for example, global variables in a module cause behavior that users of the module might not expect.

     

  • Constants, on the other hand, are safe. A constant, in Python, is a variable whose value is initialized but not changed. An example is LABEL, above.

Packages

A package is a way to organize a number of modules together as a unit. Python packages can also contain other packages.

To give us an example to talk about, consider the follow package structure:

 

package_example/
package_example/__init__.py
package_example/module1.py
package_example/module2.py
package_example/A.py
package_example/B.py

And, here are the contents:
 
# __init__.py

# Expose definitions from modules in this package.
from module1 import class1
from module2 import class2

# module1.py

class class1:
def __init__(self):
self.description = 'class #1'
def show(self):
print self.description

# module2.py

class class2:
def __init__(self):
self.description = 'class #2'
def show(self):
print self.description

# B.py

def function_b():
print 'Hello from function_b'

In order to be used as a Python package (e.g. so that modules can be imported from it) a directory must contain a file whose name is __init__.py. The code in this module is evaluated the first time a module is imported from the package.

In order to import modules from a package, you may either add the package directory to sys.path or, if the parent directory is on sys.path, use dot-notation to explicitly specify the path. In our example, you might use: "import package_example.module1".

A module in a package can import another module from the same package directly without using the path to the package. For example, the module A in our sample package package_example can import module B in the same package with "import B". Module A does not need to use "import package_example.B".

You can find additional information on packages at http://www.python.org/doc/essays/packages.html.

Suggested techniques:

 

  • In the __init__.py file, import and make available objects defined in modules in the package. Our sample package package_example does this. Then, you can use "from package_example import *" to import the package and its contents. For example:

     

    >>> from package_example import *
        >>> dir()
        ['__builtins__', '__doc__', '__file__', '__name__',
        'atexit', 'class1', 'class2', 'module1', 'module2',
        'readline', 'rlcompleter', 'sl', 'sys']
        >>>
        >>> c1 = class1()
        >>> c2 = class2()
        >>> c1.show()
        class #1
        >>> c2.show()
        class #2

     

A few additional notes:

 

  • With Python 2.3, you can collect the modules in a package into a Zip file by using PyZipFile from the Python standard library. See http://www.python.org/doc/current/lib/pyzipfile-objects.html.

     

    >>> import zipfile
        >>> a = zipfile.PyZipFile('mypackage.zip', 'w', zipfile.ZIP_DEFLATED)
        >>> a.writepy('Examples')
        >>> a.close()

    Then you can import and use this archive by inserting its path in sys.path. In the following example, class_basic_1 is a module within package mypackage:

     

    >>> import sys
        >>> sys.path.insert(0, '/w2/Txt/Training/mypackage.zip')
        >>> import class_basic_1
        Basic -- name: Apricot
        >>> obj = class_basic_1.Basic('Wilma')
        >>> obj.show()
        Basic -- name: Wilma

Options:
Printer Friendly
Email Friend

About The Author:

Dave Kuhlman has worked for many years on a variety of software development projects, in several programming languages, and on more than one platform. Because of Python's clear syntax, developer friendliness, and broad utility, Dave focuses his energy on the Python language, on systems built with Python, and on developing documentation and training materials for those systems. Dave's current work involves XML processing in Python as well as the development of tools and documentation for Zope and the CMSs (content management systems) that run on top of Zope, Dave's current platform is Debian GNU/Linux; he has installed and administers a small network composed of several Linux boxes behind a Linux router/gateway. More information about Dave's work can be found at http://www.rexx.com/~dkuhlman.

Developer Categories



Developer Tutorials
ASP
CGI & Perl
CSS
Flash
HTML
Java
JavaScript
MySQL
PHP
Python
XML

Developer Documentation

Developer Tools



Search our Developer Tutorials
  The DevSyndicate Network