About the Reviewers

Jason Chu is the CTO and part founder of Oprius Software Inc. He's developed software professionally for over 8 years. Chu started using Python in 2003 with version 2.2. When not developing personal or professional software, he spends his time teaching karate, playing go, and having fun in his hometown Victoria, BC, Canada. You'll often find him out drinking the Back Hand of God Stout at Christie's Carriage House. Michael Driscoll has been programming Python for almost 4 years and has dabbled...

Case study

Let's tie all our new object-oriented knowledge together by going through a few iterations of object-oriented design on a somewhat real-world example. The system we'll be modeling is a library catalog. Libraries have been tracking their inventory for centuries, originally using card catalogs, and, more recently, electronic inventories. Modern libraries have web-based catalogs that we can query from our home. Let's start with an analysis. The local librarian has asked us to write a new card...

Creating Python classes

We don't have to write much Python code to realize that Python is a very clean language. When we want to do something, we just do it, without having to go through a lot of setup. The ubiquitous, hello world in Python, as you've likely seen, is only one line. Similarly, the simplest class in Python 3 looks like this There's our first object-oriented program The class definition starts with the class keyword. This is followed by a name (of our choice) identifying the class, and is terminated with...

Expert Python Programming

ISBN 978-1-847194-94-7 Paperback 372 pages Best practices for designing, coding, and distributing your Python software 1. Learn Python development best practices from an expert, with detailed coverage of naming and coding conventions 2. Apply object-oriented principles, design patterns, and advanced syntax tricks 3. Manage your code with distributed version control 4. Profile and optimize your code An easy and convenient approach to testing your Python projects

Generator expressions

Sometimes we want to process a new sequence without placing a new list, set, or dictionary into system memory. If we're just looping over items one at a time, and don't actually care about having a final container object created, creating that container is a waste of memory. When processing one item at a time, we only need the current object stored in memory at any one moment. But when we create a container, all the objects have to be stored in that container before we start processing them....

Handling exceptions

Now let's look at the tail side of the exception coin. Namely, if we encounter an exception situation, how should our code react to, or recover from it We handle exceptions by wrapping any code that might throw one (whether it is exception code itself, or a call to any function or method that may have an exception raised inside it) inside a try except clause. The most basic syntax looks like this print(I caught an exception) print(executed after the exception) If we run this simple script using...

In practice

Let's explore two ways we can reuse existing code. After writing our code to replace strings in a ZIP file full of text files, we are later contracted to scale all the images in a ZIP file to 640x480. Looks like we could use a very similar paradigm to what we used in ZipReplace. The first impulse, obviously, would be to save a copy of that file and change the find_replace method to scale_image or something similar. But, that's just not cool. What if someday we want to change the unzip and zip...

List comprehensions

List comprehensions are one of the most powerful tools in Python, so people tend to think of them as advanced. They're not. Indeed, I've taken the liberty of littering previous examples with comprehensions and assuming you'd understand them. While it's true that advanced programmers use comprehensions a lot, it's not because they're advanced, it's because they're trivial, and handle some of the most common operations in programming. Let's have a look at one of those common operations, namely,...

Module variables can mimic singletons

Normally, in Python, the singleton pattern can be sufficiently mimicked by using module-level variables. It's not as safe as a singleton in that people could reassign those variables at any time, but like our discussion of private variables in Chapter 2, this is acceptable in Python. If someone has a valid reason to change those variables, why should we stop them It also doesn't stop people from instantiating multiple instances of the object, but again, if they have a valid reason to do so, why...

Modules and packages

Now that we know how to create classes and instantiate objects, it is time to think about organizing them. For small programs, we can just put all our classes into one file and put some code at the end of the file to start them interacting. However, as our projects grow, it can become difficult to find one class that needs to be edited among the many classes we've defined. This is where modules come in. Modules are simply Python files, nothing more. The single file in our small program is a...

Multiple inheritance

Multiple inheritance is a touchy subject. In principle, it's very simple a subclass that inherits from more than one parent class is able to access functionality from both of them. In practice, this is much less useful than it sounds and many expert programmers recommend against using it. So we'll start with a warning As a rule of thumb, if you think you need multiple inheritance, you're probably wrong, but if you know you need it, you're probably right. The simplest and most useful form of...

Object Oriented Programming

Harness the power of Python 3 objects Python 3 Object Oriented Programming Harness the power of Python 3 objects I I community experience distilled Python 3 Object Oriented Programming All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the...

One way to do setup and cleanup

Py.test supports setup and teardown methods similar to those used in unittest, but it provides even more flexibility. We'll discuss these briefly, since they are familiar, but they are not used as extensively as in the unittest module, as py.test provides us with a powerful funcargs facility, which we'll discuss in the next section. If we are writing class-based tests, we can use two methods called setup_method and teardown_method in basically the same way that setup and tearDown are called in...

Pytest extras

Py.test is an incredibly powerful library and it can do much much more than the basics we've discussed here. We haven't even started on its distributed testing framework (which allows tests to be run across a network of different platforms and interpreter versions), its numerous built-in or third-party plugins, how incredibly easy it is to write our own plugins, or the extensive customization and configuration architecture the framework supplies. You'll have to read the documentation at http...

Reducing boilerplate and cleaning up

After writing a few small tests, we often find that we have to do the same setup code for several related tests. For example, the following simple list subclass has three methods for simple statistical calculations class StatsList(list) def mean(self) return self int(len(self) 2) else return (self idx + self idx-1 ) 2 freqs defaultdict(int) for item in self freqs item + 1 mode_freq max(freqs.values()) modes for item, value in freqs.items() if value mode_freq modes.append(item) return modes...

Removing duplicate code

Often the code in management style classes such as zipReplace is quite generic and can be applied in many different ways. It is possible to use either composition or inheritance to help keep this code in one place, thus eliminating duplicate code. Before we look at any examples of this, let's discuss a tiny bit of theory. Specifically why is duplicate code a bad thing There are several reasons, but they all boil down to readability and maintainability. When we're writing a new piece of code...

Specifying attributes and behaviors

We now have a grasp on some basic object-oriented terminology. Objects are instances of classes that can be associated with each other. An object instance is a specific object with its own set of data and behaviors a specific orange on the table in front of us is said to be an instance of the general class of oranges. That's simple enough, but what are these data and behaviors that are associated with each object Let's start with data. Data typically represents the individual characteristics of...

Strategy example

The canonical example of the strategy pattern is sort routines over the years, numerous algorithms have been invented for sorting a collection of objects quick sort, merge sort, and heap sort are all fast sort algorithms with different features, each useful in its own right, depending on the size and type of inputs, how out of order they are, and the requirements of the system. If we have client code that needs to sort a collection, we could pass it to an object with a sort() method. This...

Strings are Unicode

At the beginning of this section, we defined strings as collections of immutable Unicode characters. This actually makes things very complicated at times, because Unicode isn't really a storage format. If you get a string of bytes from a file or a socket, for example, they won't be in Unicode. They will, in fact, be the built-in type bytes. Bytes are immutable sequences of well, bytes. Bytes are the lowest-level storage format in computing. They represent 8 bits, and are generally described as...

Table of Contents

Specifying attributes and behaviors 11 Hiding details and creating the public interface 14 Inheritance provides abstraction 22 Chapter 3 When Objects are Alike_63 Chapter 4 Expecting the Unexpected_95 What happens when an exception occurs 99 Defining our own exceptions 108 Exceptions aren't exceptional 109 Chapter 5 When to Use Object-oriented Programming_125 Using properties to add behavior to class data 129 Decorators another way to create properties 134 When should we use properties 135...

Treat objects as objects

This may seem obvious, but you should generally give separate objects in your problem domain a special class in your code. We've seen examples of this in the case studies in previous chapters the process is generally to identify objects in the problem and then model their data and behaviors. Identifying objects is a very important task in object-oriented analysis and programming. But it isn't always as easy as counting the nouns in a short paragraph, as we've been doing. Remember, objects are...

Variable argument lists

Default values alone do not allow us all the flexible benefits of method overloading. The thing that makes Python really slick is the ability to write methods that accept an arbitrary number of positional or keyword arguments without explicitly naming them. We can also pass arbitrary lists and dictionaries into such functions. For example, a function to accept a link or list of links and download the web pages could use such variadic arguments, or varargs. Instead of accepting a single value...

When should we use properties

With the property keyword smearing the division between behavior and data, it can be confusing to know which one to choose. The example use case we saw earlier is one of the most common uses of properties we have some data on a class that we later want to add behavior to. There are also other factors to take into account when deciding to use a property. Technically, in Python, data, properties, and methods are all attributes on a class. The fact that a method is callable does not distinguish it...

Why test

More and more programmers are learning how important testing their code is. If you're among them, feel free to skim this section. You'll find the next section, where we actually learn how to do the tests in Python, more scintillating. If you're not convinced of the importance of testing, I promise that your code is broken, you just don't know it. Read on Some people argue that testing is more important in Python code because of its dynamic nature compiled languages such as Java and C++ are...

Python Object Oriented Programming Exercises

Before diving into exercises for each design pattern, take a moment to implement the copy method for the File and Folder objects in the previous section. The File method should be quite trivial just create a new node with the same name and contents, and add it to the new parent folder. The copy method on Folder is quite a bit more complicated, as you first have to duplicate the folder, and then recursively copy each of it's children to the new location. You can call the copy() method on the...

Composition and inheritance

So far, we've learned to design systems as a group of interacting objects, where each interaction is viewing the objects involved at an appropriate level of abstraction. But we don't know yet how to create those levels of abstraction. There are a variety of ways to do this we'll discuss some advanced design patterns in Chapter 8 and Chapter 9. But even most design patterns rely on two basic principles known as composition and inheritance. Composition is the act of collecting together several...

A completely different way to set up variables

One of the most common uses for the various setup and teardown functions is to ensure certain class or module variables are available with a known value before each test method is run. py.test offers a completely different way to do this using what are known as funcargs, short for function arguments. Funcargs are basically named variables that are previously set up in a test configuration file. This allows us to separate configuration from execution of tests, and allows the funcargs to be used...

Extending builtins

We discussed briefly in Chapter 3 how built-in data types can be extended using inheritance. Now, we'll go into more detail as to when we would want to do that. When we have a built-in container object that we want to add functionality to, we have two options. We can either create a new object, which holds that container as an attribute composition , or we can subclass the built-in object and add or adapt methods on it to do what we want inheritance . Composition is usually the best alternative...

Testing with pytest

The Python unittest module is very verbose and requires a lot of boilerplate code to set up and initialize tests. It is based on the very popular JUnit testing framework for Java. It even uses the same method names you may have noticed they don't conform to the PEP-8 naming standard, which suggests underscores be used to separate words in a method name, rather than CamelCase and test layout. While this is effective for testing in Java, it's not necessarily the best design for Python testing....

Jinja Templating

Now, we can set up Jinja to serve some templates from a folder for us Well that was easy. This gives us a templates variable that we can use to load templates based on filename from the given folder. Before we create the CherryPy app server, let's have a look at the templates. Let's scrutinize the simple template for adding a blog article first block title New Entry endblock block content form method POST Title lt input name title type text size 40 gt lt br gt lt textarea name message rows 10...

Command pattern

The command pattern adds a level of abstraction between actions that must be done, and the object that invokes those actions, normally at a later time. In the command pattern, client code creates a Command object that can be executed at a later date. This object knows about a receiver object that manages its own internal state when the command is executed on it. The Command object implements a specific interface typically it has an execute or do_action method, and also keeps track of any...

String formatting

Python 3 has a versatile string formatting mechanism that allows us to easily construct strings comprised of hard-coded text and interspersed variables. We've used it in many previous examples, but it is much more versatile than the simple formatting specifiers we've used. Any string can be turned into a format string by calling the format method on it. This method returns a new string where specific characters in the input string have been replaced with values provided in the arguments and...

Python Design Pattern Command Object

Absolute imports 46 abstract factory pattern about 271 examples 272 implementing 273-275 UML class diagram 272 abstraction 16 access control 50, 51 adapter pattern about 257, 259 benefits 258 structure 258 UML diagram 258 add_child method 279 add_point method 127 Agent class 90 aggregation 19 all method 352 API SQLite 348 append method 170 append method 98 anchor 356 expand 356 fill 356 ipadx 356 ipady 356 padx 356 pady 356 side 357 assertDictEqual method 320 assertEqual method 318 assertFalse...

CherryPy

CherryPy version 3.2 is the first major web application server to be made available on the Python 3 platform. It can be downloaded from http cherrypy.org . It is not a full-stack framework like the very popular Django, TurboGears, or Zope libraries. These frameworks provide extra support for data storage, templating, authentication, and other common web operations. Such features are not impossible in CherryPy, you re just responsible for finding or implementing them yourself. CherryPy is a very...