Object Oriented Python ---------------------------------------- Or a class about classes! Object Oriented Programming ---------------------------------------- Object-oriented programming is about using classes to define data abstraction. A strong abstraction should make use of encapsulation, modularity, and inheritance. The Simplest Class ---------------------------------------- The simplest class .. code-block:: python class Simple(object): pass I Lied ---------------------------------------- Actually it can be simpler .. code-block:: python class Simple: pass But this is not compatible with Python 3.X so don't do it. Stepping Out a Little More (image.py) ---------------------------------------- .. literalinclude:: /code/image.py Class Initialization ---------------------------------------- The ``__init__`` method defines the class initialized. .. code-block:: python image = Image(100, 100) print image.dimensions() Know Yourself ---------------------------------------- The ``self`` is the first argument to all class methods. ``self`` similar to ``this`` in C++ or Java. Unlike ``this`` in C++ or Java, ``self`` is not a keyword only a strong convention. It represents the current class instance. It is automatically passed when the object calls the method. Class Attributes ---------------------------------------- While can ``self`` be used to store information about the current instance, you can also use class level attributes to maintain information about all class instances. To do this we can use the ``__class__`` attribute which is an attribute on all class instances. Class Attribute Example (counter.py) ---------------------------------------- .. literalinclude:: /code/counter.py Private Methods ---------------------------------------- Part of encapsulation is being able to keep information hidden. To mark a method as private you prefix the name with a double underscore. When this is done you can only call the method from inside the class. Private Method Example (private.py) ---------------------------------------- .. literalinclude:: /code/private.py Inheritance is Super ---------------------------------------- Classes do not always have to extend from object. They can extend from one or more base classes. Doing this we can extend the functionality provided by the base class. The ``super`` function delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. Inheritance Example (square.py) ---------------------------------------- .. literalinclude:: /code/square.py Extending Built-In Types ---------------------------------------- You can also extend built in Python types such as int, float, dict, list. Possible extensions: - Ordered dictionary (preserves key insersion order) - Multi-valued dictionary (allows keys to hold multiple values) - Queue (first in, first out) Note on Extending Immutable Types ---------------------------------------- ``__init__`` is called after the object is constructed. For immutable types (int, string, tuple) it is too late to modify the value. If you want to change how they are created you need to override the class constructor ``__new__``. Example Extending String (newstring.py) ---------------------------------------- .. literalinclude:: /code/newstring.py ``__new__`` vs ``__init__`` ---------------------------------------- ``__new__`` takes the class (``cls``) as its first argument. If it returns a new instance of the class then ``__init__`` is called passing the new instance and the rest of the arguments. If ``__new__`` doesn't return a new instance then ``__init__`` will not be called. If you are extending object or a subclass of object will typically not need to change this method. Singleton ---------------------------------------- One use of overriding ``__new__`` for a mutable type is the Singleton pattern. The Singleton pattern is a common programming pattern for having a class which only allows for a single instance. Singleton Implementation (singleton.py) ---------------------------------------- .. literalinclude:: /code/singleton.py :lines: 1-8 Singleton Usage (singleton.py) ---------------------------------------- .. literalinclude:: /code/singleton.py :lines: 10- The Borg Pattern ---------------------------------------- Some critics of the Singleton pattern have noted that it is often used in cases where you don't really care about object identity but really all you care about is shared state (such as global configuration). Borg Implementation (borg.py) ---------------------------------------- .. literalinclude:: /code/borg.py :lines: 1-7 Borg Usage (borg.py) ---------------------------------------- .. literalinclude:: /code/borg.py :lines: 10- Multiple Inheritance ---------------------------------------- Python supports multiple inheritance. Multiple inheritance can cause some ambiguity in what version of the method will be called. In Python methods are resolved depth-first from left to right in the defined parent classes. This means the order of base classes matter in the class definition. Method Resolution Example (multi.py) ---------------------------------------- .. literalinclude:: /code/multi.py :lines: 1-11 Mixins ---------------------------------------- Mixins are a sytle of using multiple inheritance. Each mixin class adds a small and specific piece of functionality. This would be similar to interfaces in Java or C#. Mixins Example ---------------------------------------- A great example comes right from the Python standard library: SocketServer.py .. code-block:: python class ForkingUDPServer(ForkingMixIn, UDPServer): pass class ForkingTCPServer(ForkingMixIn, TCPServer): pass class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass Defining Comparisons ---------------------------------------- Comparison methods ``__lt__``, ``__le__``, ``__eq__``, ``__ne__``, ``__gt__``, and ``__ge__`` can be used to define object comparisons. They should return either ``True`` or ``False`` but can return any value which will be converted to a bool. ``__cmp__(self, other)`` is called if the above methods are not defined. It should return a negative int if ``self < other``, zero if equal and a positive integer if ``self > other``. Comparisons Example (compare.py) ---------------------------------------- .. literalinclude:: /code/compare.py :lines: 1-10 Defining Operators ---------------------------------------- You can define common operators by defining ``__add__``, ``__sub__``, ``__mul__``, ``__floordiv__``, ``__mod__``, ``__pow__``, ``__lshift__``, ``__rshift__``, ``__and__``, ``__or__``, and ``__xor__``. Operators Example (media.py) ---------------------------------------- .. literalinclude:: /code/media.py :lines: 1-10 Up Next ---------------------------------------- Using the file system and handling problems. .. header:: MA792K Spring 2011 Lecture 3 .. footer:: © Mark Lavin 2011