Mastering Object-Oriented Python Second Edition Build powerful applications with reusable code using OOP design patterns and Python 3.7 Steven F. Lott BIRMINGHAM - MUMBAI Mastering Object-Oriented Python Second Edition Copyright © 2019 Packt Publishing 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 preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information. Commissioning Editor: Richa Tripathi Acquisition Editor: Chaitanya Nair Content Development Editor: Zeeyan Pinheiro Senior Editor: Afshaan Khan Technical Editor: Ketan Kamble Copy Editor: Safis Editing Project Coordinator: Vaidehi Sawant Proofreader: Safis Editing Indexer: Manju Arasan Production Designer: Jayalaxmi Raja First published: April 2014 Second edition: June 2019 Production reference: 1130619 Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 978-1-78953-136-7 www.packtpub.com Packt.com Subscribe to our online digital library for full access to over 7,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website. Why subscribe? Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals Improve your learning with Skill Plans built especially for you Get a free eBook or video every month Fully searchable for easy access to vital information Copy and paste, print, and bookmark content Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details. At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks. Contributors About the author Steven F. Lott has been programming since the 1970s, when computers were large, expensive, and rare. As a contract software developer and architect, he has worked on hundreds of projects, from very small to very large ones. He's been using Python to solve business problems for over 10 years. His other titles with Packt include Python Essentials, Mastering Object-Oriented Python, Functional Python Programming Second Edition, Python for Secret Agents, and Python for Secret Agents II. Steven is currently a technomad who lives in various places on the East Coast of the US. You can follow him on Twitter via the handle @s_lott. About the reviewers Cody Jackson is a disabled military veteran, the founder of Socius Consulting – an IT and business management consulting company in San Antonio – and a cofounder of Top Men Technologies. He is currently employed at CACI International as the lead ICS/SCADA modeling and simulations engineer. He has been involved in the tech industry since 1994, when he joined the Navy as a nuclear chemist and Radcon Technician. Prior to CACI, he worked at ECPI University as a computer information systems adjunct professor. A self-taught Python programmer, he is the author of Learning to Program Using Python and Secret Recipes of the Python Ninja. He holds an Associate in Science degree, a Bachelor of Science degree, and a Master of Science degree. Hugo Solis is an assistant professor in the Physics Department at the University of Costa Rica. His current research interests are computational cosmology, complexity, cryptography, and the influence of hydrogen on material properties. He has vast experience with languages, including C/C++ and Python for scientific programming. He is a member of the Free Software Foundation and has contributed code to some free software projects. He has also been a technical reviewer for Hands-On Qt for Python Developers and Learning Object-Oriented Programming, and he is the author of the Kivy Cookbook from Packt Publishing. Currently, he is in charge of the IFT, a Costa Rican scientific nonprofit organization for the multidisciplinary practice of physics. I'd like to thank Katty Sanchez, my beloved mother, for her support and vanguard thoughts. Packt is searching for authors like you If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea. Table of Contents Preface 1 Section 1: Tighter Integration Via Special Methods Chapter 1: Preliminaries, Tools, and Techniques 10 Technical requirements 11 About the Blackjack game 12 Playing the game 13 Blackjack player strategies 14 Object design for simulating Blackjack 14 The Python runtime and special methods 14 Interaction, scripting, and tools 15 Selecting an IDE 16 Consistency and style 17 Type hints and the mypy program 18 Performance – the timeit module 18 Testing – unittest and doctest 19 Documentation – sphinx and RST markup 21 Installing components 22 Summary 23 Chapter 2: The __init__() Method 24 Technical requirements 25 The implicit superclass – object 25 The base class object __init__() method 26 Implementing __init__() in a superclass 27 Creating enumerated constants 29 Leveraging __init__() via a factory function 31 Faulty factory design and the vague else clause 32 Simplicity and consistency using elif sequences 33 Simplicity using mapping and class objects 34 Two parallel mappings 35 Mapping to a tuple of values 36 The partial function solution 36 Fluent APIs for factories 37 Implementing __init__() in each subclass 38 Composite objects 40 Wrapping a collection class 41 Table of Contents Extending a collection class 42 More requirements and another design 42 Complex composite objects 43 Complete composite object initialization 45 Stateless objects without __init__() 46 Some additional class definitions 47 Multi-strategy __init__() 50 More complex initialization alternatives 52 Initializing with static or class-level methods 54 Yet more __init__() techniques 55 Initialization with type validation 58 Initialization, encapsulation, and privacy 60 Summary 62 Chapter 3: Integrating Seamlessly - Basic Special Methods 63 Technical requirements 64 The __repr__() and __str__() methods 64 Simple __str__() and __repr__() 66 Collection __str__() and __repr__() 67 The __format__() method 68 Nested formatting specifications 71 Collections and delegating format specifications 71 The __hash__() method 72 Deciding what to hash 73 Inheriting definitions for immutable objects 75 Overriding definitions for immutable objects 78 Overriding definitions for mutable objects 80 Making a frozen hand from a mutable hand 82 The __bool__() method 84 The __bytes__() method 85 The comparison operator methods 88 Designing comparisons 90 Implementation of a comparison of objects of the same class 92 Implementation of a comparison of the objects of mixed classes 94 Hard totals, soft totals, and polymorphism 95 A mixed class comparison example 97 The __del__() method 100 The reference count and destruction 101 Circular references and garbage collection 102 Circular references and the weakref module 104 The __del__() and close() methods 106 The __new__() method and immutable objects 107 The __new__() method and metaclasses 109 Metaclass example – class-level logger 111 Summary 112 [ ii ] Table of Contents Chapter 4: Attribute Access, Properties, and Descriptors 114 Technical requirements 115 Basic attribute processing 115 Attributes and the __init__() method 117 Creating properties 118 Eagerly computed properties 121 The setter and deleter properties 123 Using special methods for attribute access 124 Limiting attribute names with __slots__ 126 Dynamic attributes with __getattr__() 127 Creating immutable objects as a NamedTuple subclass 128 Eagerly computed attributes, dataclasses, and __post_init__() 129 Incremental computation with __setattr__() 131 The __getattribute__() method 133 Creating descriptors 135 Using a non-data descriptor 138 Using a data descriptor 140 Using type hints for attributes and properties 143 Using the dataclasses module 145 Attribute Design Patterns 147 Properties versus attributes 148 Designing with descriptors 148 Summary 149 Chapter 5: The ABCs of Consistent Design 150 Technical requirements 150 Abstract base classes 151 Base classes and polymorphism 153 Callable 155 Containers and collections 155 Numbers 157 Some additional abstractions 158 The iterator abstraction 158 Contexts and context managers 159 The abc and typing modules 160 Using the __subclasshook__() method 162 Abstract classes using type hints 163 Summary, design considerations, and trade-offs 164 Looking forward 165 Chapter 6: Using Callables and Contexts 166 Technical requirements 167 Designing callables 167 Improving performance 169 Using memoization or caching 171 [ iii ] Table of Contents Using functools for memoization 172 Aiming for simplicity using a callable interface 173 Complexities and the callable interface 174 Managing contexts and the with statement 176 Using the decimal context 178 Other contexts 179 Defining the __enter__() and __exit__() methods 179 Handling exceptions 181 Context manager as a factory 182 Cleaning up in a context manager 183 Summary 185 Callable design considerations and trade-offs 185 Context manager design considerations and trade-offs 186 Looking forward 187 Chapter 7: Creating Containers and Collections 188 Technical requirements 189 ABCs of collections 189 Examples of special methods 191 Using the standard library extensions 191 The typing.NamedTuple class 193 The deque class 195 The ChainMap use case 197 The OrderedDict collection 198 The defaultdict subclass 199 The counter collection 201 Creating new kinds of collections 203 Narrowing a collection's type 204 Defining a new kind of sequence 205 A statistical list 206 Choosing eager versus lazy calculation 208 Working with __getitem__(), __setitem__(), __delitem__(), and slices 211 Implementing __getitem__(), __setitem__(), and __delitem__() 213 Wrapping a list and delegating 214 Creating iterators with __iter__() 217 Creating a new kind of mapping 218 Creating a new kind of set 220 Some design rationale 222 Defining the Tree class 223 Defining the TreeNode class 225 Demonstrating the binary tree bag 229 Design considerations and tradeoffs 230 Summary 231 Chapter 8: Creating Numbers 233 [ iv ]