mastering object-oriented python

This document was uploaded by one of our users. The uploader already confirmed that they had the permission to publish it. If you are author/publisher or own the copyright of this documents, please report to us by using this DMCA report form.

Simply click on the Download Book button.

Yes, Book downloads on Ebookily are 100% Free.

Sometimes the book is free on Amazon As well, so go ahead and hit "Search on Amazon"

Author(s): steven F.Lott
Publisher: Packt Publishing Ltd.
Year: 2019

Language: English
Pages: 992

Title Page......Page 2
Copyright and Credits......Page 3
Mastering Object-Oriented Python Second Edition......Page 4
About Packt......Page 5
Why subscribe?......Page 6
Contributors......Page 7
About the author......Page 8
About the reviewers......Page 9
Packt is searching for authors like you......Page 10
Preface......Page 24
Who this book is for......Page 26
What this book covers......Page 27
To get the most out of this book......Page 30
Download the example code files......Page 31
Code in Action......Page 32
Conventions used......Page 33
Get in touch......Page 35
Reviews......Page 36
Section 1: Tighter Integration Via Special Methods......Page 37
Preliminaries, Tools, and Techniques......Page 38
Technical requirements......Page 40
About the Blackjack game......Page 41
Playing the game......Page 42
Blackjack player strategies......Page 44
Object design for simulating Blackjack......Page 45
The Python runtime and special methods......Page 46
Interaction, scripting, and tools......Page 47
Selecting an IDE......Page 49
Consistency and style......Page 50
Type hints and the mypy program......Page 51
Performance – the timeit module......Page 52
Testing – unittest and doctest......Page 53
Documentation – sphinx and RST markup......Page 55
Installing components......Page 57
Summary......Page 59
The __init__() Method......Page 60
Technical requirements......Page 62
The implicit superclass – object......Page 63
The base class object __init__() method......Page 64
Implementing __init__() in a superclass......Page 66
Creating enumerated constants......Page 68
Leveraging __init__() via a factory function......Page 70
Faulty factory design and the vague else clause......Page 72
Simplicity and consistency using elif sequences......Page 74
Simplicity using mapping and class objects......Page 75
Two parallel mappings......Page 77
Mapping to a tuple of values......Page 78
The partial function solution......Page 79
Fluent APIs for factories......Page 81
Implementing __init__() in each subclass......Page 83
Composite objects......Page 85
Wrapping a collection class......Page 87
Extending a collection class......Page 88
More requirements and another design......Page 89
Complex composite objects......Page 90
Complete composite object initialization......Page 92
Stateless objects without __init__()......Page 94
Some additional class definitions......Page 96
Multi-strategy __init__()......Page 99
More complex initialization alternatives......Page 101
Initializing with static or class-level methods......Page 104
Yet more __init__() techniques......Page 106
Initialization with type validation......Page 109
Initialization, encapsulation, and privacy......Page 112
Summary......Page 114
Integrating Seamlessly - Basic Special Methods......Page 115
Technical requirements......Page 117
The __repr__() and __str__() methods......Page 118
Simple __str__() and __repr__()......Page 120
Collection __str__() and __repr__()......Page 121
The __format__() method......Page 122
Nested formatting specifications......Page 125
Collections and delegating format specifications......Page 126
The __hash__() method......Page 127
Deciding what to hash......Page 129
Inheriting definitions for immutable objects......Page 132
Overriding definitions for immutable objects......Page 135
Overriding definitions for mutable objects......Page 138
Making a frozen hand from a mutable hand......Page 140
The __bool__() method......Page 142
The __bytes__() method......Page 144
The comparison operator methods......Page 147
Designing comparisons......Page 150
Implementation of a comparison of objects of the same class......Page 152
Implementation of a comparison of the objects of mixed classes......Page 155
Hard totals, soft totals, and polymorphism......Page 156
A mixed class comparison example......Page 159
The __del__() method......Page 162
The reference count and destruction......Page 163
Circular references and garbage collection......Page 165
Circular references and the weakref module......Page 167
The __del__() and close() methods......Page 170
The __new__() method and immutable objects......Page 171
The __new__() method and metaclasses......Page 174
Metaclass example – class-level logger......Page 176
Summary......Page 178
Attribute Access, Properties, and Descriptors......Page 180
Technical requirements......Page 182
Basic attribute processing......Page 183
Attributes and the __init__() method......Page 185
Creating properties......Page 187
Eagerly computed properties......Page 190
The setter and deleter properties......Page 192
Using special methods for attribute access......Page 194
Limiting attribute names with __slots__......Page 196
Dynamic attributes with __getattr__()......Page 197
Creating immutable objects as a NamedTuple subclass......Page 199
Eagerly computed attributes, dataclasses, and __post_init__()......Page 200
Incremental computation with __setattr__()......Page 202
The __getattribute__() method......Page 205
Creating descriptors......Page 208
Using a non-data descriptor......Page 211
Using a data descriptor......Page 214
Using type hints for attributes and properties......Page 217
Using the dataclasses module......Page 219
Attribute Design Patterns......Page 222
Properties versus attributes......Page 223
Designing with descriptors......Page 224
Summary......Page 225
The ABCs of Consistent Design......Page 226
Technical requirements......Page 227
Abstract base classes......Page 228
Base classes and polymorphism......Page 231
Callable......Page 234
Containers and collections......Page 235
Numbers......Page 237
Some additional abstractions......Page 239
The iterator abstraction......Page 240
Contexts and context managers......Page 241
The abc and typing modules......Page 242
Using the __subclasshook__() method......Page 244
Abstract classes using type hints......Page 246
Summary, design considerations, and trade-offs......Page 247
Looking forward......Page 249
Using Callables and Contexts......Page 250
Technical requirements......Page 251
Designing callables......Page 252
Improving performance......Page 255
Using memoization or caching......Page 257
Using functools for memoization......Page 259
Aiming for simplicity using a callable interface......Page 260
Complexities and the callable interface......Page 262
Managing contexts and the with statement......Page 264
Using the decimal context......Page 266
Other contexts......Page 267
Defining the __enter__() and __exit__() methods......Page 268
Handling exceptions......Page 270
Context manager as a factory......Page 271
Cleaning up in a context manager......Page 273
Summary......Page 275
Callable design considerations and trade-offs......Page 276
Context manager design considerations and trade-offs......Page 277
Looking forward......Page 278
Creating Containers and Collections......Page 279
Technical requirements......Page 280
ABCs of collections......Page 281
Examples of special methods......Page 283
Using the standard library extensions......Page 284
The typing.NamedTuple class......Page 286
The deque class......Page 288
The ChainMap use case......Page 290
The OrderedDict collection......Page 292
The defaultdict subclass......Page 293
The counter collection......Page 295
Creating new kinds of collections......Page 298
Narrowing a collection's type......Page 300
Defining a new kind of sequence......Page 302
A statistical list......Page 304
Choosing eager versus lazy calculation......Page 306
Working with __getitem__(), __setitem__(), __delitem__(), and slices......Page 310
Implementing __getitem__(), __setitem__(), and __delitem__()......Page 312
Wrapping a list and delegating......Page 314
Creating iterators with __iter__()......Page 317
Creating a new kind of mapping......Page 318
Creating a new kind of set......Page 321
Some design rationale......Page 323
Defining the Tree class......Page 324
Defining the TreeNode class......Page 326
Demonstrating the binary tree bag......Page 330
Design considerations and tradeoffs......Page 331
Summary......Page 333
Creating Numbers......Page 334
Technical requirements......Page 336
ABCs of numbers......Page 337
Deciding which types to use......Page 339
Method resolution and the reflected operator concept......Page 340
The arithmetic operator's special methods......Page 342
Creating a numeric class......Page 346
Defining FixedPoint initialization......Page 347
Defining FixedPoint binary arithmetic operators......Page 349
Defining FixedPoint unary arithmetic operators......Page 353
Implementing FixedPoint reflected operators......Page 354
Implementing FixedPoint comparison operators......Page 357
Computing a numeric hash......Page 360
Designing more useful rounding......Page 362
Implementing other special methods......Page 363
Optimization with the in-place operators......Page 365
Summary......Page 367
Decorators and Mixins - Cross-Cutting Aspects......Page 369
Technical requirements......Page 371
Class and meaning......Page 372
Type hints and attributes for decorators......Page 373
Attributes of a function......Page 375
Constructing a decorated class......Page 377
Some class design principles......Page 379
Aspect-oriented programming......Page 381
Using built-in decorators......Page 383
Using standard library decorators......Page 385
Using standard library mixin classes......Page 387
Using the enum with mixin classes......Page 388
Writing a simple function decorator......Page 390
Creating separate loggers......Page 393
Parameterizing a decorator......Page 395
Creating a method function decorator......Page 398
Creating a class decorator......Page 401
Adding methods to a class......Page 405
Using decorators for security......Page 408
Summary......Page 410
Section 2: Object Serialization and Persistence......Page 413
Serializing and Saving - JSON, YAML, Pickle, CSV, and XML......Page 414
Technical requirements......Page 417
Understanding persistence, class, state, and representation......Page 418
Common Python terminology......Page 420
Filesystem and network considerations......Page 421
Defining classes to support persistence......Page 423
Rendering blogs and posts......Page 426
Dumping and loading with JSON......Page 429
JSON type hints......Page 432
Supporting JSON in our classes......Page 433
Customizing JSON encoding......Page 435
Customizing JSON decoding......Page 438
Security and the eval() issue......Page 439
Refactoring the encode function......Page 440
Standardizing the date string......Page 442
Writing JSON to a file......Page 443
Dumping and loading with YAML......Page 444
Formatting YAML data on a file......Page 446
Extending the YAML representation......Page 448
Security and safe loading......Page 452
Dumping and loading with pickle......Page 454
Designing a class for reliable pickle processing......Page 456
Security and the global issue......Page 459
Dumping and loading with CSV......Page 460
Dumping simple sequences into CSV......Page 462
Loading simple sequences from CSV......Page 464
Handling containers and complex classes......Page 466
Dumping and loading multiple row types into a CSV file......Page 468
Filtering CSV rows with an iterator......Page 471
Dumping and loading joined rows into a CSV file......Page 473
Dumping and loading with XML......Page 476
Dumping objects using string templates......Page 478
Dumping objects with xml.etree.ElementTree......Page 481
Loading XML documents......Page 483
Summary......Page 485
Design considerations and tradeoffs......Page 486
Schema evolution......Page 488
Looking forward......Page 489
Storing and Retrieving Objects via Shelve......Page 490
Technical requirements......Page 492
Analyzing persistent object use cases......Page 493
The ACID properties......Page 495
Creating a shelf......Page 497
Designing shelvable objects......Page 499
Designing objects with type hints......Page 500
Designing keys for our objects......Page 501
Generating surrogate keys for objects......Page 503
Designing a class with a simple key......Page 504
Designing classes for containers or collections......Page 507
Referring to objects via foreign keys......Page 508
Designing CRUD operations for complex objects......Page 511
Searching, scanning, and querying......Page 513
Designing an access layer for shelve......Page 515
Writing a demonstration script......Page 519
Creating indexes to improve efficiency......Page 521
Creating a cache......Page 524
Adding yet more index maintenance......Page 525
The writeback alternative to index updates......Page 527
Schema evolution......Page 528
Summary......Page 530
Design considerations and tradeoffs......Page 531
Application software layers......Page 532
Looking forward......Page 533
Storing and Retrieving Objects via SQLite......Page 534
Technical requirements......Page 536
SQL databases, persistence, and objects......Page 537
The SQL data model – rows and tables......Page 539
CRUD processing via SQL DML statements......Page 543
Querying rows with the SQL SELECT statement......Page 547
SQL transactions and the ACID properties......Page 549
Designing primary and foreign database keys......Page 552
Processing application data with SQL......Page 554
Implementing class-like processing in pure SQL......Page 556
Mapping Python objects to SQLite BLOB columns......Page 558
Mapping Python objects to database rows manually......Page 561
Designing an access layer for SQLite......Page 563
Implementing container relationships......Page 567
Improving performance with indices......Page 570
Adding an ORM layer......Page 572
Designing ORM-friendly classes......Page 573
Building the schema with the ORM layer......Page 577
Manipulating objects with the ORM layer......Page 579
Querying posts that are given a tag......Page 582
Defining indices in the ORM layer......Page 584
Schema evolution......Page 586
Summary......Page 588
Design considerations and tradeoffs......Page 589
Mapping alternatives......Page 590
Key and key design......Page 591
Application software layers......Page 592
Looking forward......Page 593
Transmitting and Sharing Objects......Page 594
Technical requirements......Page 596
Class, state, and representation......Page 597
Using HTTP and REST to transmit objects......Page 599
Implementing CRUD operations via REST......Page 601
Implementing non-CRUD operations......Page 603
The REST protocol and ACID......Page 604
Choosing a representation – JSON, XML, or YAML......Page 606
Using Flask to build a RESTful web service......Page 607
Problem-domain objects to transfer......Page 608
Creating a simple application and server......Page 610
More sophisticated routing and responses......Page 614
Implementing a REST client......Page 617
Demonstrating and unit testing the RESTful services......Page 618
Handling stateful REST services......Page 620
Designing RESTful object identifiers......Page 621
Multiple layers of REST services......Page 623
Using a Flask blueprint......Page 624
Registering a blueprint ......Page 630
Creating a secure REST service......Page 632
Hashing user passwords......Page 635
Implementing REST with a web application framework......Page 637
Using a message queue to transmit objects......Page 639
Defining processes......Page 641
Building queues and supplying data......Page 644
Summary......Page 646
Design considerations and tradeoffs......Page 647
Schema evolution......Page 648
Application software layers......Page 649
Looking forward......Page 650
Configuration Files and Persistence......Page 651
Technical requirements......Page 653
Configuration file use cases......Page 654
Representation, persistence, state, and usability......Page 657
Application configuration design patterns......Page 659
Configuring via object construction......Page 661
Implementing a configuration hierarchy......Page 664
Storing the configuration in INI files......Page 666
Handling more literals via the eval() variants......Page 670
Storing the configuration in PY files......Page 672
Configuration via class definitions......Page 674
Configuration via SimpleNamespace......Page 676
Using Python with exec() for the configuration......Page 680
Why exec() is a non-problem......Page 682
Using ChainMap for defaults and overrides......Page 683
Storing the configuration in JSON or YAML files......Page 686
Using flattened JSON configurations......Page 688
Loading a YAML configuration......Page 690
Storing the configuration in properties files......Page 692
Parsing a properties file......Page 693
Using a properties file......Page 697
Using XML files – PLIST and others......Page 699
Customized XML configuration files......Page 702
Summary......Page 704
Design considerations and trade-offs......Page 705
Creating a shared configuration......Page 707
Schema evolution......Page 708
Looking forward......Page 709
Section 3: Object-Oriented Testing and Debugging......Page 710
Design Principles and Patterns......Page 711
Technical requirements......Page 712
The SOLID design principles......Page 713
The Interface Segregation Principle......Page 716
The Liskov Substitution Principle......Page 719
The Open/Closed Principle......Page 721
The Dependency Inversion Principle......Page 723
The Single Responsibility Principle......Page 725
A SOLID principle design test......Page 727
Building features through inheritance and composition......Page 728
Advanced composition patterns......Page 730
Parallels between Python and libstdc++......Page 733
Summary......Page 736
The Logging and Warning Modules......Page 737
Technical requirements......Page 739
Creating a basic log......Page 740
Creating a class-level logger......Page 742
Configuring loggers......Page 745
Starting up and shutting down the logging system......Page 746
Naming loggers......Page 748
Extending logger levels......Page 750
Defining handlers for multiple destinations......Page 752
Managing propagation rules......Page 755
Configuration Gotcha......Page 757
Specialized logging for control, debugging, audit, and security......Page 758
Creating a debugging log......Page 761
Creating audit and security logs......Page 764
Using the warnings module......Page 767
Showing API changes with a warning......Page 769
Showing configuration problems with a warning......Page 771
Showing possible software problems with a warning......Page 773
Advanced logging – the last few messages and network destinations......Page 775
Building an automatic tail buffer......Page 776
Sending logging messages to a remote process......Page 780
Preventing queue overrun......Page 784
Summary......Page 786
Design considerations and trade-offs......Page 787
Looking ahead......Page 789
Designing for Testability......Page 790
Technical requirements......Page 792
Defining and isolating units for testing......Page 793
Minimizing dependencies......Page 794
Creating simple unit tests......Page 798
Creating a test suite......Page 801
Including edge and corner cases......Page 803
Using mock objects to eliminate dependencies......Page 805
Using mocks to observe behaviors......Page 809
Using doctest to define test cases......Page 811
Combining doctest and unittest......Page 816
Creating a more complete test package......Page 817
Using setup and teardown......Page 819
Using setup and teardown with OS resources......Page 821
Using setup and teardown with databases......Page 823
The TestCase class hierarchy......Page 827
Using externally defined expected results......Page 829
Using pytest and fixtures......Page 833
Assertion checking......Page 835
Using fixtures for test setup......Page 836
Using fixtures for setup and teardown......Page 838
Building parameterized fixtures......Page 839
Automated integration or performance testing......Page 841
Summary......Page 843
Design considerations and trade-offs......Page 844
Looking forward......Page 846
Coping with the Command Line......Page 847
Technical requirements......Page 848
The OS interface and the command line......Page 849
Arguments and options......Page 852
Using the pathlib module......Page 854
Parsing the command line with argparse......Page 857
A simple on–off option......Page 859
An option with an argument......Page 860
Positional arguments......Page 861
All other arguments......Page 862
--version display and exit......Page 864
--help display and exit......Page 865
Integrating command-line options and environment variables......Page 866
Providing more configurable defaults......Page 868
Overriding configuration file settings with environment variables......Page 869
Making the configuration aware of the None values......Page 872
Customizing the help output......Page 873
Creating a top-level main() function......Page 875
Ensuring DRY for the configuration......Page 878
Managing nested configuration contexts......Page 879
Programming in the large......Page 881
Designing command classes......Page 882
Adding the analysis command subclass......Page 885
Adding and packaging more features into an application......Page 886
Designing a higher-level, composite command......Page 887
Additional composite Command design patterns......Page 890
Integrating with other applications......Page 892
Summary......Page 894
Design considerations and trade-offs......Page 895
Looking forward......Page 896
Module and Package Design......Page 897
Technical requirements......Page 898
Designing a module......Page 900
Some module design patterns......Page 901
Modules compared with classes......Page 903
The expected content of a module......Page 905
Whole modules versus module items......Page 907
Designing a package......Page 909
Designing a module-package hybrid......Page 911
Designing a package with alternate implementations......Page 913
Using the ImportError exception......Page 916
Designing a main script and the __main__ module......Page 917
Creating an executable script file......Page 918
Creating a __main__ module......Page 920
Programming in the large......Page 921
Designing long-running applications......Page 923
Organizing code into src, scripts, tests, and docs......Page 927
Installing Python modules......Page 929
Summary......Page 931
Design considerations and tradeoffs......Page 932
Looking forward......Page 933
Quality and Documentation......Page 934
Technical requirements......Page 936
Writing docstrings for the help() function......Page 937
Using pydoc for documentation......Page 939
Better output via RST markup......Page 943
Blocks of text......Page 945
The RST inline markup......Page 948
RST directives......Page 950
Learning RST......Page 952
Writing effective docstrings......Page 953
Writing file-level docstrings, including modules and packages......Page 955
Writing API details in RST markup......Page 957
Writing class and method function docstrings......Page 959
Writing function docstrings......Page 961
More sophisticated markup techniques......Page 962
Using Sphinx to produce the documentation......Page 964
Using Sphinx quickstart......Page 965
Writing Sphinx documentation......Page 968
Filling in the 4+1 views for documentation......Page 970
Writing the implementation document......Page 972
Creating Sphinx cross-references......Page 974
Refactoring Sphinx files into directories......Page 976
Handling legacy documents......Page 977
Writing the documentation......Page 978
Literate programming......Page 979
Use cases for literate programming......Page 980
Working with a literate programming tool......Page 982
Summary......Page 988
Design considerations and tradeoffs......Page 989
Other Books You May Enjoy......Page 990
Leave a review - let other readers know what you think......Page 992