Modern Python Cookbook
5/5
()
About this ebook
Read more from Steven F. Lott
Python for Secret Agents Rating: 0 out of 5 stars0 ratingsPython Essentials Rating: 5 out of 5 stars5/5Mastering Objectoriented Python Rating: 5 out of 5 stars5/5Modern Python Cookbook: 133 recipes to develop flawless and expressive programs in Python 3.8 Rating: 4 out of 5 stars4/5Python Real-World Projects: Craft your Python portfolio with deployable applications Rating: 0 out of 5 stars0 ratingsPython Object-Oriented Programming: Build robust and maintainable object-oriented Python applications and libraries Rating: 0 out of 5 stars0 ratingsModern Python Cookbook: 130+ updated recipes for modern Python 3.12 with new techniques and tools Rating: 0 out of 5 stars0 ratingsFunctional Python Programming, 3rd edition: Use a functional approach to write succinct, expressive, and efficient Python code Rating: 0 out of 5 stars0 ratingsSecret Recipes of the Python Ninja: Over 70 recipes that uncover powerful programming tactics in Python Rating: 0 out of 5 stars0 ratings
Related to Modern Python Cookbook
Related ebooks
Python GUI Programming Cookbook Rating: 5 out of 5 stars5/5Python Data Analysis Cookbook Rating: 5 out of 5 stars5/5Python 3 Text Processing with NLTK 3 Cookbook Rating: 4 out of 5 stars4/5Natural Language Processing: Python and NLTK Rating: 0 out of 5 stars0 ratingsWeb Development with Django Cookbook - Second Edition Rating: 0 out of 5 stars0 ratingsPractical Data Analysis Cookbook Rating: 0 out of 5 stars0 ratingsPython 3 Object-oriented Programming - Second Edition Rating: 4 out of 5 stars4/5Learning Python Rating: 5 out of 5 stars5/5Mastering Python Rating: 0 out of 5 stars0 ratingsFunctional Python Programming Rating: 0 out of 5 stars0 ratingsPython GUI Programming Cookbook - Second Edition Rating: 5 out of 5 stars5/5Python 3 Object Oriented Programming Rating: 4 out of 5 stars4/5Web Scraping with Python Rating: 4 out of 5 stars4/5Python: Journey from Novice to Expert Rating: 5 out of 5 stars5/5Python Data Structures and Algorithms Rating: 5 out of 5 stars5/5NumPy Beginner's Guide Rating: 5 out of 5 stars5/5Python: Programming for Intermediates: Learn the Fundamentals of Python in 7 Days Rating: 4 out of 5 stars4/5Python Data Analysis Rating: 4 out of 5 stars4/5Python: Programming For Intermediates: Learn The Basics Of Python In 7 Days! Rating: 0 out of 5 stars0 ratingsMastering Python Regular Expressions Rating: 5 out of 5 stars5/5Mastering Python Design Patterns Rating: 0 out of 5 stars0 ratingsPython: Real-World Data Science Rating: 0 out of 5 stars0 ratingsPython 3 Programming: A Beginner Crash Course Guide to Learn Python 3 in 1 Week Rating: 3 out of 5 stars3/5Python Parallel Programming Cookbook Rating: 5 out of 5 stars5/5Python Web Scraping - Second Edition Rating: 5 out of 5 stars5/5Learning pandas Rating: 4 out of 5 stars4/5Learning pandas - Second Edition Rating: 4 out of 5 stars4/5NumPy: Beginner's Guide - Third Edition Rating: 4 out of 5 stars4/5
Programming For You
Learn to Code. Get a Job. The Ultimate Guide to Learning and Getting Hired as a Developer. Rating: 5 out of 5 stars5/5Excel : The Ultimate Comprehensive Step-By-Step Guide to the Basics of Excel Programming: 1 Rating: 5 out of 5 stars5/5Coding All-in-One For Dummies Rating: 4 out of 5 stars4/5Python Programming : How to Code Python Fast In Just 24 Hours With 7 Simple Steps Rating: 4 out of 5 stars4/5Python QuickStart Guide: The Simplified Beginner's Guide to Python Programming Using Hands-On Projects and Real-World Applications Rating: 0 out of 5 stars0 ratingsPython Machine Learning By Example Rating: 4 out of 5 stars4/5Unreal Engine from Zero to Proficiency (Foundations): Unreal Engine from Zero to Proficiency, #1 Rating: 3 out of 5 stars3/5SQL QuickStart Guide: The Simplified Beginner's Guide to Managing, Analyzing, and Manipulating Data With SQL Rating: 4 out of 5 stars4/5Excel 101: A Beginner's & Intermediate's Guide for Mastering the Quintessence of Microsoft Excel (2010-2019 & 365) in no time! Rating: 0 out of 5 stars0 ratingsHTML & CSS: Learn the Fundaments in 7 Days Rating: 4 out of 5 stars4/5Grokking Algorithms: An illustrated guide for programmers and other curious people Rating: 4 out of 5 stars4/5Python: For Beginners A Crash Course Guide To Learn Python in 1 Week Rating: 4 out of 5 stars4/5Linux: Learn in 24 Hours Rating: 5 out of 5 stars5/5JavaScript All-in-One For Dummies Rating: 5 out of 5 stars5/5PYTHON: Practical Python Programming For Beginners & Experts With Hands-on Project Rating: 5 out of 5 stars5/5Python: Learn Python in 24 Hours Rating: 4 out of 5 stars4/5Learn PowerShell in a Month of Lunches, Fourth Edition: Covers Windows, Linux, and macOS Rating: 5 out of 5 stars5/5Beginning Programming with C++ For Dummies Rating: 4 out of 5 stars4/5Python Data Structures and Algorithms Rating: 5 out of 5 stars5/5SQL: For Beginners: Your Guide To Easily Learn SQL Programming in 7 Days Rating: 5 out of 5 stars5/5
Reviews for Modern Python Cookbook
1 rating0 reviews
Book preview
Modern Python Cookbook - Steven F. Lott
Table of Contents
Modern Python Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Why subscribe?
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Errata
Piracy
Questions
1. Numbers, Strings, and Tuples
Introduction
Creating meaningful names and using variables
Getting ready
How to do it...
Choosing names wisely
Assigning names to objects
How it works...
There's more...
See also
Working with large and small integers
Getting ready
How to do it...
How it works...
There's more...
See also
Choosing between float, decimal, and fraction
Getting ready
How to do it...
Doing currency calculations
Fraction calculations
Floating-point approximations
Converting numbers from one type to another
How it works...
There's more...
See also
Choosing between true division and floor division
Getting ready
How to do it...
Doing floor division
Doing true division
Rational fraction calculations
How it works...
See also
Rewriting an immutable string
Getting ready
How to do it...
Slicing a piece of a string
Updating a string with a replacement
Making a string all lowercase
Removing extra punctuation marks
How it works...
There's more...
See also
String parsing with regular expressions
Getting ready
How to do it...
How it works...
There's more...
See also
Building complex strings with template
.format()
Getting ready
How to do it...
How it works...
There's more...
See also
Building complex strings from lists of characters
Getting ready
How to do it...
How it works...
There's more
See also
Using the Unicode characters that aren't on our keyboards
Getting ready
How to do it...
How it works...
See also
Encoding strings – creating ASCII and UTF-8 bytes
Getting ready
How to do it...
How it works...
See also
Decoding bytes – how to get proper characters from some bytes
Getting ready
How to do it..
How it works...
See also
Using tuples of items
Getting ready
How to do it...
Creating tuples
Extracting items from a tuple
How it works...
There's more
See also...
2. Statements and Syntax
Introduction
Writing Python script and module files – syntax basics
Getting ready
How to do it...
How it works...
There's more...
See also
Writing long lines of code
Getting ready
How to do it...
Using backslash to break a long statement into logical lines
Using the () characters to break a long statement into sensible pieces
Using string literal concatenation
Assigning intermediate results to separate variables
How it works...
There's more...
See also
Including descriptions and documentation
Getting ready
How to do it...
Writing docstrings for scripts
Writing docstrings for library modules
How it works...
There's more...
See also
Writing better RST markup in docstrings
Getting ready
How to do it...
How it works...
There's more...
Using directives
Using inline markup
See also
Designing complex if...elif chains
Getting ready
How to do it...
How it works...
There's more...
See also
Designing a while statement which terminates properly
Getting ready
How to do it...
How it works...
See also
Avoiding a potential problem with break statements
Getting ready
How to do it...
How it works...
There's more...
See also
Leveraging the exception matching rules
Getting ready
How to do it...
How it works...
There's more...
See also
Avoiding a potential problem with an except: clause
Getting ready
How to do it...
How it works...
See also
Chaining exceptions with the raise from statement
Getting ready
How to do it...
How it works...
There's more...
See also
Managing a context using the with statement
Getting ready
How to do it...
How it works...
There's more...
See also
3. Function Definitions
Introduction
Designing functions with optional parameters
Getting ready
How to do it...
Particular to General Design
General to Particular design
How it works...
There's more...
See also
Using super flexible keyword parameters
Getting ready
How to do it...
How it works...
There's more...
See also
Forcing keyword-only arguments with the * separator
Getting ready
How to do it...
How it works...
There's more...
See also
Writing explicit types on function parameters
Getting ready
How to do it...
How it works...
There's more...
See also
Picking an order for parameters based on partial functions
Getting ready
How to do it...
Wrapping a function
Creating a partial function with keyword parameters
Creating a partial function with positional parameters
How it works...
There's more...
See also
Writing clear documentation strings with RST markup
Getting ready
How to do it...
How it works...
There's more...
See also
Designing recursive functions around Python's stack limits
Getting ready
How to do it...
How it works...
There's more...
See also
Writing reusable scripts with the script library switch
Getting ready
How to do it...
How it works...
There's more...
See also
4. Built-in Data Structures – list, set, dict
Introduction
Choosing a data structure
Getting ready
How to do it...
How it works...
There's more...
See also
Building lists – literals, appending, and comprehensions
Getting ready
How to do it...
Building a list with the append() method
Writing a list comprehension
Using the list function on a generator expression
How it works...
There's more...
Other ways to extend a list
See also
Slicing and dicing a list
Getting ready
How to do it...
How it works...
There's more...
See also
Deleting from a list – deleting, removing, popping, and filtering
Getting ready
How to do it...
Deleting items from a list
The remove() method
The pop() method
The filter() function
How it works...
There's more...
See also
Reversing a copy of a list
Getting ready
How to do it...
How it works...
See also
Using set methods and operators
Getting ready
How to do it...
How it works...
There's more...
See also
Removing items from a set – remove(), pop(), and difference
Getting ready
How to do it...
How it works...
There's more...
See also
Creating dictionaries – inserting and updating
Getting ready
How to do it...
How it works...
There's more...
See also
Removing from dictionaries – the pop() method and the del statement
Getting ready
How to do it...
How it works...
There's more...
See also
Controlling the order of dict keys
Getting ready
How to do it...
How it works...
There's more...
See also
Handling dictionaries and sets in doctest examples
Getting ready
How to do it...
How it works...
There's more...
Understanding variables, references, and assignment
How to do it...
How it works...
There's more...
See also
Making shallow and deep copies of objects
Getting ready
How to do it...
How it works...
See also
Avoiding mutable default values for function parameters
Getting ready
How to do it...
How it works...
There's more...
See also
5. User Inputs and Outputs
Introduction
Using features of the print() function
Getting ready
How to do it...
How it works...
There's more...
See also
Using input() and getpass() for user input
Getting ready
How to do it...
How it works...
There's more...
Input string parsing
Interaction via the cmd module
See also
Debugging with format
.format_map(vars())
Getting ready
How to do it...
How it works...
There's more...
See also
Using argparse to get command-line input
Getting ready
How to do it...
How it works...
There's more...
See also
Using cmd for creating command-line applications
Getting ready
How to do it...
How it works...
There's more...
See also
Using the OS environment settings
Getting ready
How to do it...
How it works...
There's more...
See also
6. Basics of Classes and Objects
Introduction
Using a class to encapsulate data and processing
Getting ready
How to do it...
How it works...
There's more...
See also
Designing classes with lots of processing
Getting ready
How to do it...
How it works...
There's more...
See also
Designing classes with little unique processing
Getting ready
How to do it...
Stateless objects
Stateful objects with a new class
Stateful objects using an existing class
How it works...
There's more...
See also
Optimizing small objects with __slots__
Getting ready
How to do it...
How it works...
There's more...
See also
Using more sophisticated collections
Getting ready
How to do it...
How it works...
There's more...
See also
Extending a collection – a list that does statistics
Getting ready
How to do it...
How it works...
There's more...
See also
Using properties for lazy attributes
Getting ready...
How to do it...
How it works...
There's more...
See also...
Using settable properties to update eager attributes
Getting ready
How to do it...
How it works...
There's more...
Initialization
Calculation
See also
7. More Advanced Class Design
Introduction
Choosing between inheritance and extension – the is-a question
Getting ready
How to do it...
Wrapping – aggregation and composition
Extending - inheritance
How it works...
There's more...
See also
Separating concerns via multiple inheritance
Getting ready
How to do it...
How it works...
There's more...
See also
Leveraging Python's duck typing
Getting ready
How to do it...
How it works...
There's more...
See also
Managing global and singleton objects
Getting ready
How to do it...
Module global variable
Class-level static variable
How it works...
There's more...
Using more complex structures – maps of lists
Getting ready
How to do it...
How it works...
There's more...
See also
Creating a class that has orderable objects
Getting ready
How to do it...
How it works...
There's more...
See also
Defining an ordered collection
Getting ready
How to do it...
How it works...
There's more...
See also
Deleting from a list of mappings
Getting ready
How to do it...
How it works...
There's more...
See also
8. Functional and Reactive Programming Features
Introduction
Writing generator functions with the yield statement
Getting ready
How to do it...
How it works...
There's more...
See also
Using stacked generator expressions
Getting ready
How to do it...
How it works...
There's more...
Namespace instead of list
See also
Applying transformations to a collection
Getting ready...
How to do it...
How it works...
There's more...
See also...
Picking a subset - three ways to filter
Getting ready...
How to do it...
How it works...
There's more...
See also...
Summarizing a collection – how to reduce
Getting ready
How to do it...
How it works...
There's more...
Maxima and minima
Potential for abuse
Combining map and reduce transformations
Getting ready
How to do it...
How it works...
There's more...
See also
Implementing there exists
processing
Getting ready
How to do it...
How it works...
There's more...
The itertools module
Creating a partial function
Getting ready
How to do it...
Using functools.partial()
Creating a lambda object
How it works...
There's more...
Simplifying complex algorithms with immutable data structures
Getting ready
How to do it...
How it works...
There's more...
Writing recursive generator functions with the yield from statement
Getting ready
How to do it...
How it works...
There's more...
See also
9. Input/Output, Physical Format, and Logical Layout
Introduction
Using pathlib to work with filenames
Getting ready
How to do it...
Making the output filename by changing the input suffix
Making a number of sibling output files with distinct names
Creating a directory and a number of files
Comparing file dates to see which is newer
Removing a file
Finding all files that match a given pattern
How it works...
There's more...
See also
Reading and writing files with context managers
Getting ready
How to do it...
How it works...
There's more...
See also
Replacing a file while preserving the previous version
Getting ready
How to do it...
How it works...
There's more...
See also
Reading delimited files with the CSV module
Getting ready
How to do it...
How it works...
There's more...
See also
Reading complex formats using regular expressions
Getting ready
How to do it...
Defining the parse function
Using the parse function
How it works...
There's more...
See also
Reading JSON documents
Getting ready
How to do it...
How it works...
There's more...
Serializing a complex data structure
Deserializing a complex data structure
See also
Reading XML documents
Getting ready
How to do it...
How it works...
There's more...
See also
Reading HTML documents
Getting ready
How to do it...
How it works...
There's more...
See also
Upgrading CSV from DictReader to namedtuple reader
Getting ready
How to do it...
How it works...
There's more...
See also
Upgrading CSV from a DictReader to a namespace reader
Getting ready
How to do it...
How it works...
There's more...
See also
Using multiple contexts for reading and writing files
Getting ready
How to do it...
How it works...
There's more...
See also
10. Statistical Programming and Linear Regression
Introduction
Using the built-in statistics library
Getting ready
How to do it...
How it works...
There's more...
Average of values in a Counter
Getting ready
How to do it...
How it works...
There's more...
See also
Computing the coefficient of a correlation
Getting ready
How to do it...
How it works...
There's more...
Computing regression parameters
Getting ready
How to do it...
How it works...
There's more...
Computing an autocorrelation
Getting ready
How to do it...
How it works...
There's more...
Long-term model
See also
Confirming that the data is random – the null hypothesis
Getting ready
How to do it...
How it works...
There's more...
See also
Locating outliers
Getting ready
How to do it...
How it works...
There's more...
See also
Analyzing many variables in one pass
Getting ready
How to do it...
How it works...
There's more...
Using map()
See also
11. Testing
Introduction
Using docstrings for testing
Getting ready
How to do it...
Writing examples for stateless functions
Writing examples for stateful objects
How it works...
There's more...
See also
Testing functions that raise exceptions
Getting ready
How to do it...
How it works...
There's more...
See also
Handling common doctest issues
Getting ready
How to do it...
Writing doctest examples for mapping or set values
Writing doctest examples for floating-point values
How it works...
There's more...
See also
Creating separate test modules and packages
Getting ready
How to do it...
How it works...
There's more...
Some other assertions
Separate tests directory
See also
Combining unittest and doctest tests
Getting ready
How to do it...
How it works...
There's more...
See also
Testing things that involve dates or times
Getting ready
How to do it...
How it works...
There's more...
See also
Testing things that involve randomness
Getting ready
How to do it...
How it works...
There's more...
See also
Mocking external resources
Getting ready
Creating an entry document in the entrylog collection
Seeing a typical response
Client class for database access
How to do it...
How it works...
Creating a context manager
Creating a dynamic, stateful test
Mocking a complex object
Using the load_tests protocol
There's more...
See also
12. Web Services
Introduction
Implementing web services with WSGI
Getting ready
How to do it...
How it works...
There's more...
See also
Using the Flask framework for RESTful APIs
Getting ready
How to do it...
How it works...
There's more...
See also
Parsing the query string in a request
Getting ready
How to do it...
How it works...
There's more...
See also
Making REST requests with urllib
Getting ready
How to do it...
How it works...
There's more...
The OpenAPI (Swagger) specification
Adding Swagger to the server
See also
Parsing the URL path
Getting ready
How to do it...
Server
Client
How it works...
Deck slicing
Client side
There's more...
Providing a Swagger specification
Using a Swagger specification
See also
Parsing a JSON request
Getting ready
How to do it...
Swagger specification
Server
Client
How it works...
There's more...
Location header
Additional resources
Query for a specific player
Exception handling
See also
Implementing authentication for web services
Getting ready
Configuring SSL
Users and credentials
Flask view function decorator
How to do it...
Defining the User class
Defining a view decorator
Creating the server
Creating an example client
How it works...
There's more...
Creating a command-line interface
Building the Authentication header
See also
13. Application Integration
Introduction
Finding configuration files
Getting ready
Why so many choices?
How to do it...
How it works...
There's more...
See also
Using YAML for configuration files
Getting ready
How to do it...
How it works...
There's more...
See also
Using Python for configuration files
Getting ready
How to do it...
How it works...
There's more...
See also
Using class-as-namespace for configuration
Getting ready
How to do it...
How it works...
There's more...
Configuration representation
See also
Designing scripts for composition
Getting ready
How to do it...
How it works...
There's more...
Designing as a class hierarchy
See also
Using logging for control and audit output
Getting ready
How to do it...
How it works...
There's more...
Combining two applications into one
Getting ready
How to do it...
How it works...
There's more...
Refactoring
Concurrency
Logging
See also
Combining many applications using the Command design pattern
Getting ready
How to do it...
How it works...
There's more...
See also
Managing arguments and configuration in composite applications
Getting ready
How to do it...
How it works...
The Command design pattern
There's more...
See also
Wrapping and combining CLI applications
Getting ready
How to do it...
How it works...
There's more...
Unit test
See also
Wrapping a program and checking the output
Getting ready
How to do it...
How it works...
There's more...
See also
Controlling complex sequences of steps
Getting ready
How to do it...
How it works...
There's more...
Building conditional processing
See also
Modern Python Cookbook
Modern Python Cookbook
Copyright © 2016 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, and its dealers and distributors will be held liable for any damages caused or alleged to be 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.
First published: November 2016
Production reference: 1211116
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.
ISBN 978-1-78646-925-0
www.packtpub.com
Credits
About the Author
Steven F. Lott has been programming since the 70s, 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. He's been using Python to solve business problems for over 10 years.
He’s currently leveraging Python to implement microservices and ETL pipelines. His other titles with Packt Publishing include Python Essentials, Mastering Object-Oriented Python, Functional Python Programming, and Python for Secret Agents.
Steven is currently a technomad who lives in various places on the east coast of the U.S. His technology blog is http://slott-softwarearchitect.blogspot.com and his LinkedIn address is https://www.linkedin.com/in/steven-lott-029835.
About the Reviewers
Sanjeev Jaiswal is a computer graduate with 7 years of industrial experience in web development and cyber security. He basically uses Perl, Python, and GNU/Linux for his day-to-day activities. He is currently working on projects involving penetration testing, source code review, and security design and implementations.
He is very much interested in web and cloud security. You can follow him on Twitter at @aliencoders and on GitHub at https://github.com/jassics.
He has written Instant PageSpeed Optimization and co-authored Learning Django Web Development for Packt Publishing. He has reviewed more than 5 books for Packt Publishing and looks forward to authoring or reviewing more books for Packt Publishing and other publishers.
Vahid Mirjalili is a software engineer and data scientist, currently working towards his PhD study in Computer Science at Michigan State University. His research at the i-PRoBE (integrated pattern recognition and biometrics) lab involves attribute classification of face images from large image datasets.
Furthermore, he teaches Python programming as well as computing concepts for data analysis and databases. Owing to his specialty in data mining, he is very interested in predictive modeling and getting insights from data. He is also a Python developer and likes to contribute to the open source community.
Moreover, he enjoys making tutorials for different directions of data science and computer algorithms, which can be found in his GitHub repository at http://github.com/mirjalil/DataScience.
www.PacktPub.com
For support files and downloads related to your book, please visit www.PacktPub.com.
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.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at service@packtpub.com for more details.
At www.PacktPub.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.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Why subscribe?
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Preface
Python is the preferred choice of developers, engineers, data scientists, and hobbyists everywhere. It is a great scripting language that can power your applications and provide great speed, safety, and scalability. By exposing Python as a series of simple recipes, you can gain insights into specific language features in a particular context. Having a tangible context helps make the language or standard library feature easier to understand.
This book takes a recipe-based approach, where each recipe addresses specific problems and issues.
What this book covers
Chapter 1, Numbers, Strings, and Tuples, will look at the different kinds of numbers, work with strings, use tuples, and use the essential built-in types in Python. We will also exploit the full power of the Unicode character set.
Chapter 2, Statements and Syntax, will cover some basics of creating script files first. Then we’ll move on to looking at some of the complex statements, including if, while, for, try, with, and raise.
Chapter 3, Function Definitions, will look at a number of function definition techniques. We’ll also look at the Python 3.5 typing module and see how we can create more formal annotations for our functions.
Chapter 4, Built-in Data Structures – list, set, dict, will look at an overview of the various structures that are available and what problems they solve. From there, we can look at lists, dictionaries, and sets in detail, and also look at some more advanced topics related to how Python handles references to objects.
Chapter 5, User Inputs and Outputs, will explain how to use the different features of the print() function. We'll also look at the different functions used to provide user input.
Chapter 6, Basics of Classes and Objects, will create classes that implement a number of statistical formulae.
Chapter 7, More Advanced Class Design, will dive a little more deeply into Python classes. We will combine some features we have previously learned about to create more sophisticated objects.
Chapter 8, Functional and Reactive Programming Features, provides us with methods to writing small, expressive functions that perform the required data transformations. Moving ahead, you will learn about the idea of reactive programming, that is, having processing rules that are evaluated when the inputs become available or change.
Chapter 9, Input/Output, Physical Format, Logical Layout, will work with different file formats such as JSON, XML, and HTML.
Chapter 10, Statistical Programming and Linear Regression, will look at some basic statistical calculations that we can do with Python’s built-in libraries and data structures. We’ll look at the questions of correlation, randomness, and the null hypothesis.
Chapter 11, Testing, will give us a detailed description of the different testing frameworks used in Python.
Chapter 12, Web Services, will look at a number of recipes for creating RESTful web services and also serving static or dynamic content.
Chapter 13, Application Integration, will look at ways that we can design applications that can be composed to create larger, more sophisticated composite applications. We’ll also look at the complications that can arise from composite applications and the need to centralize some features, such as command-line parsing.
What you need for this book
All you need to follow through the examples in this book is a computer running any recent version of Python. While the examples all use Python 3, they can be adapted to work with Python 2 only a few changes.
Who this book is for
The book is for web developers, programmers, enterprise programmers, engineers, and big data scientists. If you are a beginner, Python Cookbook will get you started. If you are experienced, it will expand your knowledge base. A basic knowledge of programming would help.
Conventions
In this book, you will find a number of text styles that distinguish between different kinds of information. Here are some examples of these styles and an explanation of their meaning.
Code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles are shown as follows: We can include other contexts through the use of the include directive.
A block of code is set as follows:
if distance is None:
distance = rate * time
elif rate is None:
rate = distance / time
elif time is None:
time = distance / rate
Any command-line input or output is written as follows:
>>> circumference_diameter_ratio = 355/113 >>> target_color_name = 'FireBrick' >>> target_color_rgb = (178, 34, 34)
New terms and important words are shown in bold.
Note
Warnings or important notes appear in a box like this.
Tip
Tips and tricks appear like this.
Reader feedback
Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of.
To send us general feedback, simply e-mail feedback@packtpub.com, and mention the book's title in the subject of your message.
If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
Downloading the example code
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the SUPPORT tab at the top.
Click on Code Downloads & Errata.
Enter the name of the book in the Search box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on Code Download.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Modern-Python-Cookbook. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.
To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.
Please contact us at copyright@packtpub.com with a link to the suspected pirated material.
We appreciate your help in protecting our authors and our ability to bring you valuable content.
Questions
If you have a problem with any aspect of this book, you can contact us at questions@packtpub.com, and we will do our best to address the problem.
Chapter 1. Numbers, Strings, and Tuples
We'll cover these recipes to introduce basic Python data types:
Creating meaningful names and using variables
Working with large and small integers
Choosing between float, decimal, and fraction
Choosing between true division and floor division
Rewriting an immutable string
String parsing with regular expressions
Building complex strings with template
.format()
Building complex strings from lists of characters
Using the Unicode characters that aren't on our keyboards
Encoding strings – creating ASCII and UTF-8 bytes
Decoding bytes – how to get proper characters from some bytes
Using tuples of items
Introduction
This chapter will look at some central types of Python objects. We'll look at the different kinds of numbers, working with strings, and using tuples. We'll look at these first because they're the simplest kinds of data Python works with. In later chapters, we'll look at data collections.
Most of these recipes assume a beginner's level of understanding of Python 3. We'll be looking at how we use the essential built-in types available in Python—numbers, strings, and tuples. Python has a rich variety of numbers, and two different division operators, so we'll need to look closely at the choices available to us.
When working with strings, there are several common operations that are important. We'll explore some of the differences between bytes—as used by our OS files, and Strings—as used by Python. We'll look at how we can exploit the full power of the Unicode character set.
In this chapter, we'll show the recipes as if we're working from the >>> prompt in interactive Python. This is sometimes called the read-eval-print loop (REPL). In later chapters, we'll look more closely at writing script files. The goal is to encourage interactive exploration because it's a great way to learn the language.
Creating meaningful names and using variables
How can we be sure our programs make sense? One of the core elements of making expressive code is to use meaningful names. But what counts as meaningful? In this recipe, we'll review some common rules for creating meaningful Python names.
We'll also look at some of Python's assignment statement variations. We can, for example, assign more than one variable in a single statement.
Getting ready
The core issue when creating a name is to ask ourselves the question what is this thing? For software, we'd like a name that's descriptive of the object being named. Clearly, a name like x is not very descriptive, it doesn't seem to refer to an actual thing.
Vague, non-descriptive names are distressingly common in some programming. It's not helpful to others when we use them. A descriptive name helps everyone.
When naming things, it's also important to separate the problem domain—what we're really trying to accomplish—from the solution domain. The solution domain consists of the technical details of Python, OS, and Internet. Anyone who reads the code can see the solution; it doesn't require deep explanation. The problem domain, however, can be obscured by technical details. It's our job to make the problem clearly visible. Well-chosen names will help.
How to do it...
We'll look at names first. Then we'll move on to assignment.
Choosing names wisely
On a purely technical level, Python names must begin with a letter. They can include any number of letters, digits, and the _ character. Python 3 is based on Unicode, so a letter is not limited to the Latin alphabet. While the A-Z Latin alphabet is commonly used, it's not required.
When creating a descriptive variable, we want to create names that are both specific and articulate the relationships among things in our programs. One widely used technique is to create longer names in a style that moves from particular to general.
The steps to choosing a name are as follows:
The last part of the name is a very broad summary of the thing. In a few cases, this may be all we need; context will supply the rest. We'll suggest some typical broad summary categories later.
Use a prefix to narrow this name around your application or problem domain.
If needed, put more narrow and specialized prefixes on this name to clarify how it's distinct from other classes, modules, packages, functions, and other objects. When in doubt about prefixing, remember how domain names work. Think of mail.google.com—the name flows from particular to general. There's no magic about the three levels of naming, but it often happens to work out that way.
Format the name depending on how it's used in Python. There are three broad classes of things we'll put names on, which are shown as follows:
Classes: A class has a name that summarizes the objects that are part of the class. These names will (often) use CapitalizedCamelCase. The first letter of a class name is capitalized to emphasize that it's a class, not an instance of the class. A class is often a generic concept, rarely a description of a tangible thing.
Objects: A name for an object usually uses snake_case - all lowercase with multiple _ characters between words. In Python, this includes variables, functions, modules, packages, parameters, attributes of objects, methods of classes, and almost everything else.
Script and module files: These are really the OS resources, as seen by Python. Therefore, a filename should follow the conventions for Python objects, using letters, the _ characters and ending with the .py extension. It's technically possible to have pretty wild and free filenames. Filenames that don't follow Python rules can be difficult to use as a module or package.
How do we choose the broad category part of a name? The general category depends on whether we're talking about a thing or a property of a thing. While the world is full of things, we can create some board groupings that are helpful. Some of the examples are Document, Enterprise, Place, Program, Product, Process, Person, Asset, Rule, Condition, Plant, Animal, Mineral, and so on.
We can then narrow these with qualifiers:
FinalStatusDocument
ReceivedInventoryItemName
The first example is a class called Document. We've narrowed it slightly by adding a prefix to call it a StatusDocument. We narrowed it even further by calling it a FinalStatusDocument. The second example is a Name that we narrowed by specifying that it's a ReceivedInventoryItemName. This example required a four-level name to clarify the class.
An object often has properties or attributes. These have a decomposition based in the kind of information that's being represented. Some examples of terms that should be part of a complete name are amount, code, identifier, name, text, date, time, datetime, picture, video, sound, graphic, value, rate, percent, measure, and so on.
The idea is to put the narrow, more detailed description first, and the broad kind of information last:
measured_height_value
estimated_weight_value
scheduled_delivery_date
location_code
In the first example, height narrows a more general representation term value. And measured_height_value further narrows this. Given this name, we can expect to see other variations on height. Similar thinking applies to weight_value, delivery_date and location_code. Each of these has a narrowing prefix or two.
Note
Some things to avoid:
Don't include detailed technical type information using coded prefixes or suffixes. This is often called Hungarian Notation; we don't use f_measured_height_value where the f is supposed to mean a floating-point. A variable like measured_height_value can be any numeric type and Python will do all the necessary conversions. The technical decoration doesn't offer much help to someone reading our code, because the type specification can be misleading or even incorrect.
Don't waste a lot of effort forcing names to look like they belong together. We don't need to make SpadesCardSuit, ClubsCardSuit, and so on. Python has many different kinds of namespaces, including packages, modules, and classes, as well as namespace objects to gather related names together. If you combine these names in a CardSuit class, you can use CardSuit.Spades, which uses the class as namespace to separate these names from other, similar names.
Assigning names to objects
Python doesn't use static variable definitions. A variable is created when a name is assigned to an object. It's important to think of the objects as central to our processing, and variables as little more than sticky notes that identify an object. Here's how we use the fundamental assignment statement:
Create an object. In many of the examples we'll create objects as literals. We'll use 355 or 113 as literal representations of integer objects in Python. We might use a string like FireBrick or a tuple like (178, 34, 34).
Write the following kind of statement: variable = object. Here are some examples:
>>> circumference_diameter_ratio = 355/113>>> target_color_name = 'FireBrick'>>> target_color_rgb = (178, 34, 34)
We've created some objects and assigned them to variables. The first object is the result of a calculation. The next two objects are simple literals. Generally, objects are created by expressions that involve functions or classes.
This basic statement isn't the only kind of assignment. We can assign a single object to multiple variables using a kind of duplicated assignment like this:
>>> target_color_name = first_color_name = 'FireBrick'
This creates two names for the same string object. We can confirm this by checking the internal ID values that Python uses:
>>> id(target_color_name) == id(first_color_name) True
This comparison shows us that the internal identifiers for these two objects are the same.
Note
A test for equality uses ==. Simple assignment uses =.
When we look at numbers and collections, we'll see that we can combine assignment with an operator. We can do things like this:
>>> total_count = 0 >>> total_count += 5 >>> total_count += 6 >>> total_count 11
We've augmented assignment with an operator. total_count += 5 is the same as total_count = total_count + 5. This technique has the advantage of being shorter.
How it works...
This approach to creating names follows the pattern of using narrow, more specific qualifiers first and the wider, less-specific category last. This follows the common convention used for domain names and e-mail addresses.
For example, a domain name like mail.google.com has a specific service, a more general enterprise, and finally a very general domain. This follows the principle of narrow-to-wider.
As another example, service@packtpub.com starts with a specific destination name, has a more general enterprise, and finally a very general domain. Even the name of destination (PacktPub) is a two-part name with a narrow enterprise name (Packt) followed by a wider industry (Pub, short for publishing). (We don't agree with those who suggest it stands for Public House.)
The assignment statement is the only way to put a name on an object. We noted that we can have two names for the same underlying object. This isn't too useful right now. But in Chapter 4, Built-in Data Structures – list, set, dict we'll see some interesting consequences of multiple names for a single object.
There's more...
We'll try to show descriptive names in all of the recipes.
Tip
We have to grant exceptions to existing software which doesn't follow this pattern. It's often better to be consistent with legacy software than impose new rules even if the new rules are better.
Almost every example will involve assignment to variables. It's central to stateful object-oriented programming.
We'll look at classes and class names in Chapter 6, Basics of Classes and Objects; we'll look at modules in Chapter 13, Application Integration.
See also
The subject of descriptive naming is a source of ongoing research and discussion. There are two aspects—syntax and semantics. The starting point for thoughts on Python syntax is the famous Python Enhancement Proposal number 8 (PEP-8). This leads to use of CamelCase, and snake_case names.
Also, be sure to do this:
>>> import this
This will provide more insight into Python ideals.
Note
For information on semantics, look at the legacy UDEF and NIEM Naming and Design Rules standards (http://www.opengroup.org/udefinfo/AboutTheUDEF.pdf). Additional details are in ISO11179 (https://en.wikipedia.org/wiki/ISO/IEC_11179), which talks in detail about meta-data and naming.
Working with large and small integers
Many programming languages make a distinction between integers, bytes, and long integers. Some languages include distinctions for signed versus unsigned integers. How do we map these concepts to Python?
The easy answer is that we don't. Python handles integers of all sizes in a uniform way. From bytes to immense numbers with hundreds of digits, it's all just integers to Python.
Getting ready
Imagine you need to calculate something really big. For example, calculate the number of ways to permute the cards in a 52-card deck. The number 52! = 52 × 51 × 50 × ... × 2 × 1, is a very, very large number. Can we do this in Python?
How to do it...
Don't worry. Really. Python behaves as if it has one universal type of integer, and this covers all of the bases from bytes to numbers that fill all of the memory. Here are the steps to using integers properly:
Write the numbers you need. Here are some smallish numbers: 355, 113. There’s no practical upper limit.
Creating a very small value—a single byte—looks like this:
>>> 22
Or perhaps this, if you want to use base 16:
>>> 0xff255
In later recipes, we'll look at a sequence of bytes that has only a single value in it:
>>> b'\xfe'b'\xfe'
This isn't—technically—an integer. It has a prefix of b' that shows us it's a 1-byte sequence.
Creating a much, much bigger number with a calculation might look like this:
>>> 2**2048 323...656
This number has 617 digits. We didn't show all of them.
How it works...
Internally, Python uses two kinds of numbers. The conversion between these two is seamless and automatic.
For smallish numbers, Python will generally use 4 or 8 byte integer values. Details are buried in CPython's internals, and depend on the facilities of the C-compiler used to build Python.
For largish numbers, over sys.maxsize, Python switches to large integer numbers which are sequences of digits. Digit, in this case, often means a 30-bit value.
How many ways can we permute a standard deck of 52 cards? The answer is 52! ≈ 8 × 10⁶⁷. Here's how we can compute that large number. We'll use the factorial function in the math module, shown as follows:
>>> import math >>> math.factorial(52) 80658175170943878571660636856403766975289505440883277824000000000000
Yes, these giant numbers work perfectly.
The first parts of our calculation of 52! (from 52 × 51 × 50 × ... down to about 42) could be performed entirely using the smallish integers. After that, the rest of the calculation had to switch to largish integers. We don't see the switch; we only see the results.
For some of the details on the internals of integers, we can look at this:
>>> import sys >>> import math >>> math.log(sys.maxsize, 2) 63.0 >>> sys.int_info sys.int_info(bits_per_digit=30, sizeof_digit=4)
The sys.maxsize value is the largest of the small integer values. We computed the log to base 2 to find out how many bits are required for this number.
This tells us that our Python uses 63-bit values for small integers. The range of smallish integers is from -2⁶⁴ ... 2⁶³ - 1. Outside this range, largish integers are used.
The values in sys.int_info tells us that large integers are a sequence of numbers that use 30-bit digits, and each of these digits occupies 4 bytes.
A large value like 52! consists of 8 of these 30-bit-sized digits. It can be a little confusing to think of a digit as requiring 30 bits to represent. Instead of 10 symbols used to represent base 10 numbers, we'd need 2**30 distinct symbols for each digit of these large numbers.
A calculation involving a number of big integer values can consume a fair bit of memory. What about small numbers? How can Python manage to keep track of lots of little numbers like one and zero?
For the commonly used numbers (-5 to 256) Python actually creates a secret pool of objects to optimize memory management. You can see this when you check the id() value for integer objects:
>>> id(1) 4297537952 >>> id(2) 4297537984 >>> a=1+1 >>> id(a) 4297537984
We've shown the internal id for the integer 1 and the integer 2. When we calculate a value, the resulting object turns out to be the same integer 2 object that was found in the pool.
When you try this, your id() values may be different. However, every time the value of 2 is used, it will be the same object; on the author's laptop, it's id = 4297537984. This saves having many, many copies of the 2 object cluttering up memory.
Here's a little trick for seeing exactly how huge a number is:
>>> len(str(2**2048)) 617
We created a string from a calculated number. Then we asked what the length of the string was. The response tells us that the number had 617 digits.
There's more...
Python offers us a broad set of arithmetic operators: +, -, *, /, //, %, and **. The / and // are for division; we'll look at these in a separate recipe named Choosing between true division and floor division. The ** raises a number to a power.
For dealing with individual bits, we have some additional operations. We can use &, ^, |, <<, and >>. These operators work bit-by-bit on the internal binary representations of integers. These compute a binary AND, a binary Exclusive OR, Inclusive OR, Left Shift, and Right Shift respectively.
While these will work on very big integers, they don't really make much sense outside the world of individual bytes. Some binary files and network protocols will involve looking at the bits within an individual byte of data.
We can play around with these operators by using the bin() function to see what's going on.
Here's a quick example of what we mean:
>>> xor = 0b0011 ^ 0b0101 >>> bin(xor) '0b110'
We've used 0b0011 and 0b0101 as our two strings of bits. This helps to clarify precisely what the two numbers have as their binary representation. We applied the exclusive or (^) operator to these two sequences of bits. We used the bin() function to see the result as a string of bits. We can carefully line up the bits to see what the operator did.
We can decompose a byte into portions. Say we want to separate the left-most two bits from the other six bits. One way to do this is with bit-fiddling expressions like these:
>>> composite_byte = 0b01101100 >>> bottom_6_mask = 0b00111111 >>> bin(composite_byte >> 6) '0b1' >>> bin(composite_byte & bottom_6_mask) '0b101100'
We've defined a composite byte which has 01 in the most significant two bits, and 101100 in the least significant six bits. We used the >> shift operator to shift the value by six positions, removing the least significant bits and preserving the two most significant bits. We used the & operator with a mask. Where the mask has 1 bit, a position's value is preserved in the result, where a mask has 0 bits, the result position is set to 0.
See also
We'll look at the two division operators in the Choosing between true division and floor division recipe
We'll look at other kinds of numbers in the Choosing between float, decimal, and fraction recipe
For details on integer processing, see https://www.python.org/dev/peps/pep-0237/
Choosing between float, decimal, and fraction
Python offers us several ways to work with rational numbers and approximations of irrational numbers. We have three basic choices:
Float
Decimal
Fraction
With so many choices, when do we use each of these?
Getting ready
It's important to be sure about our core mathematical expectations. If we're not sure what kind of data we have, or what kinds of results we want to get, we really shouldn't be coding. We need to take a step back and review things with pencil and paper.
There are three general cases for math that involve numbers beyond integers, which are:
Currency: Dollars, cents, or euros. Currency generally has a fixed number of decimal places. There are rounding rules used to determine what 7.25% of $2.95 is.
Rational Numbers or Fractions: When we're working with American units for feet and inches, or cooking measurements in cups and fluid ounces, we often need to work in fractions. When we scale a recipe that serves eight, for example, down to five people, we're doing fractional math using a scaling factor of 5/8 . How do we apply this to 2/3 cup of rice and still get a measurement that fits an American kitchen gadget?
Irrational Numbers: This includes all other kinds of calculations. It's important to note that digital computers can only approximate these numbers, and we'll occasionally see odd little artifacts of this approximation. The float approximations are very fast, but sometimes suffer from truncation issues.
When we have one of the first two cases, we should avoid floating-point numbers.
How to do it...
We'll look at each of the three cases separately. First, we'll look at computing with currency. Then we'll look at rational numbers, and finally irrational or floating-point numbers. Finally, we'll look at making explicit conversions among these various types.
Doing currency calculations
When working with currency, we should always use the decimal module. If we try to use Python's built-in float values, we'll have problems with rounding and truncation of numbers.
To work with currency, we'll do this. Import the Decimal class from the decimal module:
>>> from decimal import Decimal
Create Decimal objects from strings or integers:
>>> from decimal import Decimal>>> tax_rate = Decimal('7.25')/Decimal(100)>>> purchase_amount = Decimal('2.95')>>> tax_rate * purchase_amountDecimal('0.213875')
We created the tax_rate from two Decimal objects. One was based on a string, the other based on an integer. We could have used Decimal('0.0725') instead of doing the division explicitly.
The result is a hair over $0.21. It's computed out correctly to the full number of decimal places.
If you try to create decimal objects from floating-point values, you'll see unpleasant artifacts of float approximations. Avoid mixing Decimal and float. To round to the nearest penny, create a penny object:
>>> penny=Decimal('0.01')
Quantize your data using this penny object:
>>> total_amount = purchase_amount + tax_rate*purchase_amount>>> total_amount.quantize(penny)Decimal('3.16')
This shows how we can use the default rounding rule of ROUND_HALF_EVEN.
Every financial wizard has a different style of rounding. The Decimal module offers every variation. We might, for example, do something like this:
>>> import decimal >>> total_amount.quantize(penny, decimal.ROUND_UP) Decimal('3.17')
This shows the consequences of using a different rounding rule.
Fraction calculations
When we're doing calculations that have exact fraction values, we can use the fractions module. This provides us handy rational numbers that we can use. To work with fractions, we’ll do this:
Import the Fraction class from the fractions module:
>>> from fractions import Fraction
Create Fraction objects from strings, integers, or pairs of integers. If you create fraction objects from floating-point values, you may see unpleasant artifacts of float approximations. When the denominator is a power of 2, things can work out exactly:
>>> from fractions import Fraction>>> sugar_cups = Fraction('2.5')>>> scale_factor = Fraction(5/8)>>> sugar_cups * scale_factorFraction(25, 16)
We created one fraction from a string, 2.5. We created the second fraction from a floating-point calculation, 5/8. Because the denominator is a power of 2, this works out exactly.
The result, 25/16, is a complex-looking fraction. What's a nearby fraction that might be simpler?
>>> Fraction(24,16) Fraction(3, 2)
We can see that we'll use almost a cup and a half to scale the recipe for five people instead of eight.
Floating-point approximations
Python's built-in float type is capable of representing a wide variety of values. The trade-off here is that float often involves an approximation. In some cases—specifically when doing division that involves powers of 2—it can be as exact as a fraction. In all other cases, there may be small discrepancies that reveal the differences between the implementation of float and the mathematical ideal of an irrational number.
To work with float, we often need to round values to make them look sensible. Recognize that all calculations are an approximation:
>>> (19/155)*(155/19)0.9999999999999999
Mathematically, the value should be 1. Because of the approximations used for float, the answer isn't exact. It's not wrong by much, but it's wrong. When we round appropriately, the value is more useful:
>>> answer= (19/155)*(155/19)
>>> round(answer, 3)
1.0
Know the error term. In this case, we know what the exact answer is supposed to be, so we can compare our calculation with the known correct answer. This gives us the general error value that can creep into floating-point numbers:
>>> 1-answer1.1102230246251565e-16
For most floating-point errors, this is the typical value—about 10-16. Python has clever rules that hide this error some of the time by doing some automatic rounding. For this calculation, however, the error wasn't hidden.
This is a very important consequence.
Tip
Don't compare floating-point values for exact equality.
When we see code that uses an exact == test between floating-point numbers, there are going to be problems when the approximations differ by a single bit.
Converting numbers from one type to another
We can use the float() function to create a float value from another value. It looks like this:
>>> float(total_amount) 3.163875 >>> float(sugar_cups * scale_factor) 1.5625
In the first example, we converted a Decimal value to float. In the second example, we converted a Fraction value to float.
As we just saw, we're never happy trying to convert float to Decimal or Fraction:
>>> Fraction(19/155) Fraction(8832866365939553, 72057594037927936) >>> Decimal(19/155) Decimal('0.12258064516129031640279123394066118635237216949462890625')
In the first example, we did a calculation among integers to create a float value that has a known truncation problem. When we created a Fraction from that truncated float value, we got some terrible looking numbers that exposed the details of the truncation.
Similarly, the second example tried to create a Decimal value from a float.
How it works...
For these numeric types, Python offers us a variety of operators: +, -, *, /, //, %, and **. These are for addition, subtraction, multiplication, true division, truncated division, modulus, and raising to a power. We'll look at the two division operators in the Choosing between true division and floor division recipe.
Python is adept at converting numbers between the various types. We can mix int and float values; the integers will be promoted to floating-point to provide the most accurate answer possible. Similarly, we can mix int and Fraction and the results will be Fractions. We can also mix int and Decimal. We cannot casually mix Decimal with float or Fraction; we need to provide explicit conversions.
Note
It's important to note that float values are really approximations. The Python syntax allows us to write numbers as decimal values; that's not how they're processed internally.
We can write a value like this in Python, using ordinary base-10 values:
>>> 8.066e+67 8.066e+67
The actual value used internally will involve a binary approximation of the decimal value we wrote.
The internal value for this example, 8.066e+67, is this:
>>> 6737037547376141/2**53*2**226 8.066e+67
The numerator is a big number, 6737037547376141. The denominator is always 2⁵³. Since the denominator is fixed, the resulting fraction can only have 53 meaningful bits of data. Since more bits aren't available, values might get truncated. This leads to tiny discrepancies between our idealized abstraction and actual numbers. The exponent (2²²⁶) is required to scale the fraction up to the proper range.
Mathematically, 6737037547376141 * 2²²⁶/2⁵³.
We can use math.frexp() to see these internal details of a number:
>>> import math >>> math.frexp(8.066E+67) (0.7479614202861186, 226)
The two parts are called the mantissa and the exponent. If we multiply the mantissa by 2⁵³, we always get a whole number, which is the numerator of the binary fraction.
Note
The error we noticed earlier matches this quite nicely: 10-16 ≈ 2-53 .
Unlike the built-in float, a Fraction is an exact ratio of two integer values. As we saw in the Working with large and small integers recipe, integers in Python can be very large. We can create ratios which involve integers with a large number of digits. We're not limited by a fixed denominator.
A Decimal value, similarly, is based on a very large integer value, and a scaling factor to determine where the decimal place goes. These numbers can be huge and won't suffer from peculiar representation issues.
Note
Why use floating-point? Two reasons:
Not all computable numbers can be represented as fractions. That's why mathematicians introduced (or perhaps discovered) irrational numbers. The built-in float type is as close as we can get to the mathematical abstraction of irrational numbers. A value like √2, for example, can't be represented as a fraction.
Also, float values are very fast.
There's more...
The Python math module contains a number of specialized functions for working with floating-point values. This module includes common functions such as square root, logarithms, and various trigonometry functions. It has some other functions such as gamma, factorial, and the Gaussian error function.
The math module includes several functions that can help us do more accurate floating-point calculations. For example, the math.fsum() function will compute a floating-point sum more carefully than the built-in sum() function. It's less susceptible to approximation issues.
We can also make use of the math.isclose() function to compare two floating-point values to see if they're nearly equal:
>>> (19/155)*(155/19) == 1.0 False >>> math.isclose((19/155)*(155/19), 1) True
This function provides us with a way to compare floating-point numbers meaningfully.
Python also offers complex data. This involves a real and an imaginary part. In Python, we write 3.14+2.78j to represent the complex number 3.14 + 2.78 √-1. Python will comfortably convert between float and complex. We have the usual group of operators available for complex numbers.
To support complex numbers, there's a cmath package. The cmath.sqrt() function, for example, will return a complex value rather than raise an exception when extracting the square root of a negative number. Here's an example:
>>> math.sqrt(-2) Traceback (most recent call last): File
, line 1, in
This is essential when working with complex numbers.
See also
We'll talk more about floating point and fractions in the Choosing between true division and floor division recipe
See https://en.wikipedia.org/wiki/IEEE_floating_point
Choosing between true division and floor division
Python offers us two kinds of division operators. What