This is a very brief discussion of some selected topics about using classes in Python. This is NOT a complete coverage of the topic!
For more complete and official information on classes in Python, see the Python documentation: http://docs.python.org/tutorial/classes.html
A class is just a recipe for a closure over a collection of functions ("methods") and a collection of data ("fields" or "attributes").
An object is an instance of a closure with its associated methods and attributes, as defined by a class.
class MyClassName: def __init__(self, param1, param2, etc...): """ Constructor for the class with zero or more input parameters: param1, param2, etc. The self parameter is required here, but not used when the constructor is called. """ # create andintialize self.attribute1 = param1 self.attribute2 = param2 etc. def method1(self, paramA, paramB): """ A method with zero or more input parameters: param1, param2, etc. The self parameter is required here, but not used when the constructor is called. """ # method code here # attributes referred to as self.attribute1, etc.
Note that all methods, including the constructor of a class must have "self" as their first input parameter. When calling methods of an object or using the constructor, the "self" parameter is ignored as it is implicitly passed by the Python intepreter.
The above warning will cause Python interpreter to give errors stating that the number of required input parameters is one more than the code needs to supply.
A constructor is a special method called "__init__" that is used to initialize the an object instance when it is created from a class definition. Most commonly, the constructor initializes the attributes of the object.
Usage: aMyClassObject = MyClass(param1, param2) # as many parameters as defined by __init__, not including self.
Python has the handy, but extremely dangerous feature that the first time an attribute is assigned a value, within the class definition code, by the syntax "self.xx = aValue" where "xx" is the desired name of the attribute, the attribute is created and initialized. Typically this is done in the constructor.
Usage:
Inside the class definition:
self.xx = aValue
aValue = self.xx
Outside the class definition:
myObject.xx = aValue
aValue = myObject.xx
By convention, any attrbute who's name is preceeded with one or two underscores is treated as a "private" attribute, not to be accessed from outside of the class code, i.e. from an object instance. Using a preceeding double underscore also incurs some additional protections, so that is the recommended convention.
In general, the best practice is to treat all attributes as private and explicitly control access by defining "accessor" methods, getXX() and setXX() to get and set the value of the XX attribute.
Methods of a class are defined the same as any function except that they
Usage:
Inside the class definition:
aResult = self.aMethod(aValue1, aValue2) # self parameter is ignored
Outside the class definition:
aResult = myObject.aMethod(aValue1, aValue2) # self parameter is ignored
The same naming conventions as for attributes concerning "private" methods apply.
In general, these methods almost are never called directly by user code, but can be important in defining an object's behavior.
__eq__(self, other)
This method is used to determine equality between objects. object1 == object2 is equivalent to object1.__eq(object2)
In general, even if two objects of the same class have the same values for their attributes, they are NOT equal because they are different instances. The __eq__ method is used to override that behavior.
__hash__(self)
This function returns an integer "hash" value which is used by the Python system and in many data structures, such as dictionaries, to quickly identify an object. Note that the hash value does NOT have to be unique for any given object, but it is better if it is.
However, if two objects are equal, as defined by __eq__, then their returned values from __hash__() MUST also be equal.
This method must be defined if an object is to be used as a key in a dictionary. Most dictionaries are implemented as hash tables.
For more information on hashing, see, for instance, the Wikipedia article on hash functions. In addtion to its use here, hashing is a very important part of modern cryptography.
__str__(self)
This function defines the string representation of an object. The returned string from this method is the result of called str(myObject).
By default, if this method is not explicitly defined, the string representation of an object is a combination of its class name and its hash value.
Use this method to define a more "friendly" or informative string representation of the object instances of your classes.
One of the key notions in any object-oriented system is that classes can be related to each other through an "inheritance" relationship. Simply put, when one class, the "subclass", inherits from (is derived from) another class, the "superclass", the subclass is automatically endowed with all the abilities (read: methods) of the superclass. In addition, the subclass may also inherit the ability to access the internal data of the superclass -- this is always true in Python but not always true in most other languages.
But inheritance is much, much more than a simple labor-saving convenience. It is a cornerstone of the abstract decomposition of a problem, a vital tool in expressing abstraction:
A superclass is an abstraction of all of its subclasses.
In particular, this means that if a piece of code is written such that it works with the superclass, any instances of its subclasses will also work in that same code. This notion is called "polymorphism" -- th e ability of a subclass to be used anywhere its superclass can.
A subclass is abstractly equivalent to its superclass.
An instance of a subclass is an instance of its superclass
Inheritance and polymorphism are just two sides of the same coin. Inheritance looks at the subclass-superclass relationship from the subclass's point of view and polymorphism looks at the same relationship from the superclass's point of view.
Syntax and Usage Synopsis (see Python documentation for full details):
class MySuperClass: """"Superclass definition=""" def __init__(self,param1): """Superclass constructor with parameters""" self._data1 = param1 def method1(self, x): """A method of the superclass""" # legal to access self._data here class MySubClassA(MySuperClass): """ A subclass of MySuperClass""" def __init__(self, param1, param2): MySuperClass.__init__(self, param1) # call superclass constructor to intialize self._dataA = param2 # initialize data for this subclass def methodA(self, x): """ A method of this subclass""" # legal to access self._data here # Also legal to access self._dataA class MySubClassB(MySuperClass): """ Another subclass of MySuperClass""" def __init__(self, param1, param2): MySuperClass.__init__(self, param1) # call superclass constructor to intialize self._dataB = param2 # initialize data for this subclass def methodB(self, x): """ A method of this subclass""" # legal to access self._data here # Also legal to access self._dataB # Cannot access self._dataA p1 = "p1" p2 = 42 a = MySubClassA(p1, p2) # new instance of MySubClassA b = MySubClassB(p1, p2) # new instance of MySubClassB # Either a or b can be used anywhere that a MySuperClass object can be used. p = 99 a.method1(p) # legal call -- inherited from MySuperClass b.method1(p) # legal call -- inherited from MySuperClass a.methodA(p) # legal call -- method of MySubClassA b.methodB(p) # legal call -- method of MySubClassB a.methodB(p) # illegal call! -- NOT method of MySubClassA b.methodA(p) # illegal call! -- Not method of MySubClassB