Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Object-oriented Python

You're reading from   Mastering Object-oriented Python If you want to master object-oriented Python programming this book is a must-have. With 750 code samples and a relaxed tutorial, it's a seamless route to programming Python.

Arrow left icon
Product type Paperback
Published in Apr 2014
Publisher Packt
ISBN-13 9781783280971
Length 634 pages
Edition Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Steven F. Lott Steven F. Lott
Author Profile Icon Steven F. Lott
Steven F. Lott
Arrow right icon
View More author details
Toc

Table of Contents (26) Chapters Close

Mastering Object-oriented Python
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Some Preliminaries
1. The __init__() Method FREE CHAPTER 2. Integrating Seamlessly with Python Basic Special Methods 3. Attribute Access, Properties, and Descriptors 4. The ABCs of Consistent Design 5. Using Callables and Contexts 6. Creating Containers and Collections 7. Creating Numbers 8. Decorators and Mixins – Cross-cutting Aspects 9. Serializing and Saving – JSON, YAML, Pickle, CSV, and XML 10. Storing and Retrieving Objects via Shelve 11. Storing and Retrieving Objects via SQLite 12. Transmitting and Sharing Objects 13. Configuration Files and Persistence 14. The Logging and Warning Modules 15. Designing for Testability 16. Coping With the Command Line 17. The Module and Package Design 18. Quality and Documentation Index

Complex composite objects


The following is an example of a blackjack Hand description that might be suitable for emulating play strategies:

class Hand:
    def __init__( self, dealer_card ):
        self.dealer_card= dealer_card
        self.cards= []
    def hard_total(self ):
        return sum(c.hard for c in self.cards)
    def soft_total(self ):
        return sum(c.soft for c in self.cards)

In this example, we have an instance variable self.dealer_card based on a parameter of the __init__() method. The self.cards instance variable, however, is not based on any parameter. This kind of initialization creates an empty collection.

To create an instance of Hand, we can use the following code:

d = Deck()
h = Hand( d.pop() )
h.cards.append( d.pop() )
h.cards.append( d.pop() )

This has the disadvantage that a long-winded sequence of statements is used to build an instance of a Hand object. It can become difficult to serialize the Hand object and rebuild it with an initialization such as this one. Even if we were to create an explicit append() method in this class, it would still take multiple steps to initialize the collection.

We could try to create a fluent interface, but that doesn't really simplify things; it's merely a change in the syntax of the way that a Hand object is built. A fluent interface still leads to multiple method evaluations. When we take a look at the serialization of objects in Part 2, Persistence and Serialization we'd like an interface that's a single class-level function, ideally the class constructor. We'll look at this in depth in Chapter 9, Serializing and Saving - JSON, YAML, Pickle, CSV, and XML.

Note also that the hard total and soft total method functions shown here don't fully follow the rules of blackjack. We return to this issue in Chapter 2, Integrating Seamlessly with Python – Basic Special Methods.

Complete composite object initialization

Ideally, the __init__() initializer method will create a complete instance of an object. This is a bit more complex when creating a complete instance of a container that contains an internal collection of other objects. It'll be helpful if we can build this composite in a single step.

It's common to have both a method to incrementally accrete items as well as the initializer special method that can load all of the items in one step.

For example, we might have a class such as the following code snippet:

class Hand2:
    def __init__( self, dealer_card, *cards ):
        self.dealer_card= dealer_card
        self.cards = list(cards)
    def hard_total(self ):
        return sum(c.hard for c in self.cards)
    def soft_total(self ):
        return sum(c.soft for c in self.cards)

This initialization sets all of the instance variables in a single step. The other methods are simply copies of the previous class definition. We can build a Hand2 object in two ways. This first example loads one card at a time into a Hand2 object:

d = Deck()
P = Hand2( d.pop() )
p.cards.append( d.pop() )
p.cards.append( d.pop() )

This second example uses the *cards parameter to load a sequence of Cards class in a single step:

d = Deck()
h = Hand2( d.pop(), d.pop(), d.pop() )

For unit testing, it's often helpful to build a composite object in a single statement in this way. More importantly, some of the serialization techniques from the next part will benefit from a way of building a composite object in a single, simple evaluation.

You have been reading a chapter from
Mastering Object-oriented Python
Published in: Apr 2014
Publisher: Packt
ISBN-13: 9781783280971
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime