Movatterモバイル変換


[0]ホーム

URL:


Packt
Search iconClose icon
Search icon CANCEL
Subscription
0
Cart icon
Your Cart(0 item)
Close icon
You have no products in your basket yet
Save more on your purchases!discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Profile icon
Account
Close icon

Change country

Modal Close icon
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timerSALE ENDS IN
0Days
:
00Hours
:
00Minutes
:
00Seconds
Home> Programming> Programming Language> Modern Python Cookbook
Modern Python Cookbook
Modern Python Cookbook

Modern Python Cookbook: 130+ updated recipes for modern Python 3.12 with new techniques and tools , Third Edition

Arrow left icon
Profile Icon Steven F. Lott
Arrow right icon
₹799.99₹3276.99
Full star iconFull star iconFull star iconFull star iconHalf star icon4.9(21 Ratings)
eBookJul 2024818 pages3rd Edition
eBook
₹799.99 ₹3276.99
Paperback
₹4096.99
Subscription
Free Trial
Renews at ₹800p/m
eBook
₹799.99 ₹3276.99
Paperback
₹4096.99
Subscription
Free Trial
Renews at ₹800p/m

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Table of content iconView table of contentsPreview book icon Preview Book

Modern Python Cookbook

1
Numbers, Strings, and Tuples

This chapter will look at some of the central types of Python objects. We’ll look at working with different kinds of numbers, working with strings, and using tuples. These are the simplest kinds of data that Python works with. In later chapters, we’ll look at data structures built on these foundations.

While these recipes start with a beginner’s level of understanding of Python 3.12, they also provide some deeper background for those familiar with the language. In particular, we’ll look at some details of how numbers are represented internally, because this can help when confronted with more advanced numerical programming problems. This will help us distinguish the uses cases for the rich variety of numeric types.

We’ll also look at the two different division operators. These have distinct use cases, and we’ll look at one kind of algorithm that demands truncated division.

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 used to represent Unicode text. 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 the prompt that’s provided when runningpython from the command line or using the Python console in manyIntegrated Development Environment(IDE) tools. This is sometimes called theread-evaluate-print loop(REPL). In later chapters, we’ll change the style so it looks more like a script file. One goal of this chapter is to encourage interactive exploration because it’s a great way to learn the language.

We’ll cover these recipes to introduce basic Python data types:

We’ll start with numbers, work our way through strings, and end up working with simple combinations of objects in the form of tuples andNamedTuple objects.

1.1Choosing between float, decimal, and fraction

Python offers several ways to work with rational numbers and approximations of irrational numbers. We have three basic choices:

  • Float

  • Decimal

  • Fraction

When we have choices, it helps to have some criteria for making a selection.

1.1.1Getting ready

There are three general cases for expressions that involve numbers beyond integers, which are:

  1. Currency: Dollars, cents, euros, and so on. Currency generally has a fixed number of decimal places and rounding rules to properly quantize results.

  2. Rational Numbers or Fractions: When we scale a recipe that serves eight, for example, down to five people, we’re doing fractional math using a scaling factor of5 8.

  3. Floating Point: This includes all other kinds of calculations. This also includes irrational numbers, likeπ, root extraction, and logarithms.

When we have one of the first two cases, we should avoid floating-point numbers.

1.1.2How to do it...

We’ll look at each of the three cases separately.

Doing currency calculations

When working with currency, we should always use thedecimal module. If we try to use the values of Python’s built-infloat type, we can run into problems with the rounding and truncation of numbers:

  1. To work with currency, import theDecimal class from thedecimal module:

    >>> from decimal import Decimal
  2. We need to createDecimal objects from strings or integers. In this case, we want 7.25%, which is7.25 100. We can compute the value usingDecimal objects:

    >>> tax_rate = Decimal(’7.25’)/Decimal(100)  >>> purchase_amount = Decimal(’2.95’)  >>> tax_rate * purchase_amount  Decimal(’0.213875’)

    We could also useDecimal(’0.0725’) instead of doing the division explicitly.

  3. To round to the nearest penny, create apenny object:

    >>> penny = Decimal(’0.01’)
  4. Quantize the result using thepenny object:

    >>> total_amount = purchase_amount + tax_rate * purchase_amount  >>> total_amount.quantize(penny)  Decimal(’3.16’)

This uses the default rounding rule ofROUND_HALF_EVEN. TheDecimal module offers other rounding variations. 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 thefractions module to create rational numbers. In this example, we want to scale a recipe for eight down to five people, using58 of each ingredient. When the recipe calls for 21 2 cups of rice, what does that scale down to?

To work with fractions, we’ll do this:

  1. Import theFraction class from thefractions module:

    >>> from fractions import Fraction
  2. CreateFraction objects from strings, integers, or pairs of integers. We created one fraction from a string, ’2.5’. We created the second fraction from a floating-point expression,5 / 8. Thisonlyworks when the denominator is a power of 2:

    >>> sugar_cups = Fraction(’2.5’)  >>> scale_factor = Fraction(5/8)  >>> sugar_cups * scale_factor  Fraction(25, 16)

We can see that we’ll use almost a cup and a half of rice to scale the recipe for five people instead of eight. While float values will often be useful for rational fractions, they may not be exact unless the denominator is a power of two.

Floating-point approximations

Python’s built-infloat type can represent a wide variety of values. The trade-off here is that a float value is often an approximation. There may be a small discrepancy that reveals the differences between the implementation offloat and the mathematical ideal of an irrational number:

  1. To work withfloat, we often need to round values to make them look sensible. It’s important to recognize that all float calculations are an approximation:

    >>> (19/155)*(155/19)  0.9999999999999999
  2. Mathematically, the value should be 1. Because of the approximations used, the computed result isn’t exactly 1. We can useround(answer, 3) to round to three digits, creating a value that’s more useful:

    >>> answer = (19/155)*(155/19)  >>> round(answer, 3)  1.0

Approximations have a very important consequence.

Don’t compare floating-point values for exact equality.

Code that uses an exact== test between floating-point numbers has the potential to cause problems when two approximations differ by a single bit.

The float approximation rules come from the IEEE, and are not a unique feature of Python. Numerous programming languages work with float approximations and have identical behavior.

1.1.3How it works...

For these numeric types, Python offers a variety of operators:+,-,*,/,//,%, and**. These are for addition, subtraction, multiplication, true division, truncated division, modulo, and raising to a power, respectively. We’ll look at the two division operators,/ and//, in theChoosing between true division and floordivision recipe.

Python will do some conversions between the various numeric types. We can mixint andfloat values; the integers will be promoted to floating-point to provide the most accurate answer possible. Similarly, we can mixint andFraction as well as mixingint andDecimal. Note that we cannot casually mixDecimal with float orFraction; an explicit conversion function will be required.

It’s important to note that float values are approximations. The Python syntax allows us to write floating-point values using base 10 digits; however, that’s not how values are represented internally.

We can write the value 8.066×1067 like this in Python:

>>> 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 is this:

>>> (6737037547376141/(2**53))*(2**226)  8.066e+67

The numerator is a big number,6737037547376141. The denominator is always 253. This is why values can get truncated.

We can use themath.frexp() function to see these internal details of a number:

>>> import math  >>> math.frexp(8.066E+67)  (0.7479614202861186, 226)

The two parts are called themantissa(orsignificand) and theexponent. If we multiply the mantissa by 253, we always get a whole number, which is the numerator of the binary fraction.

Unlike the built-in float, aFraction is an exact ratio of two integer values. We can create ratios that involve integers with a very large number of digits. We’re not limited by a fixed denominator.

ADecimal value, similarly, is based on a very large integer value, as well as a scaling factor to determine where the decimal place goes. These numbers can be huge and won’t suffer from peculiar representation issues.

1.1.4There’s more...

The Pythonmath module contains several specialized functions for working with floating-point values. This module includes common elementary functions such as square root, logarithms, and various trigonometry functions. It also has some other functions such as gamma, factorial, and the Gaussian error function.

Themath module includes several functions that can help us do more accurate floating-point calculations. For example, themath.fsum() function will compute a floating-point sum more carefully than the built-insum() function. It’s less susceptible to approximation issues.

We can also make use of themath.isclose() function to compare two floating-point values, an expression, and a literal1.0, to see if they’re nearly equal:

>>> (19/155)*(155/19) == 1.0  False  >>> math.isclose((19/155)*(155/19), 1.0)  True

This function provides us with a way to compare two floating-point numbers meaningfully for near-equality.

Python also offerscomplexnumbers. A complex number has a real and an imaginary part. In Python, we write3.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 thecmath package. Thecmath.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):  ...  ValueError: math domain error  >>> import cmath  >>> cmath.sqrt(-2)  1.4142135623730951j

This module is helpful when working with complex numbers.

1.1.5See also

1.2Choosing between true division and floor division

Python offers us two kinds of division operators. What are they, and how do we know which one to use? We’ll also look at the Python division rules and how they apply to integer values.

1.2.1Getting ready

There are several general cases for division:

  • Adiv-modpair: We want both parts – the quotient and the remainder. The name refers to the division and modulo operations combined together. We can summarize the quotient and remainder asq,r= (a b,a modb).

    We often use this when converting values from one base into another. When we convert seconds into hours, minutes, and seconds, we’ll be doing adiv-modkind of division. We don’t want the exact number of hours; we want a truncated number of hours, and the remainder will be converted into minutes and seconds.

  • Thetruevalue: This is a typical floating-point value; it will be a good approximation to the quotient. For example, if we’re computing an average of several measurements, we usually expect the result to be floating-point, even if the input values are all integers.

  • Arational fractionvalue: This is often necessary when working in American units of feet, inches, and cups. For this, we should be using theFraction class. When we divideFraction objects, we always get exact answers.

We need to decide which of these cases apply, so we know which division operator to use.

1.2.2How to do it...

We’ll look at these three cases separately.

Doing floor division

When we are doing thediv-modkind of calculations, we might use the floor division operator,//, and the modulo operator,%. The expressiona % b gives us the remainder from an integer division ofa // b. Or, we might use thedivmod() built-in function to compute both at once:

  1. We’ll divide the number of seconds by 3,600 to get the value of hours. The modulo, or remainder in division, computed with the% operator, can be converted separately into minutes and seconds:

    >>> total_seconds = 7385  >>> hours = total_seconds // 3600  >>> remaining_seconds = total_seconds % 3600
  2. Next, we’ll divide the number of seconds by 60 to get minutes; the remainder is the number of seconds less than 60:

    >>> minutes = remaining_seconds // 60  >>> seconds = remaining_seconds % 60  >>> hours, minutes, seconds  (2, 3, 5)

Here’s the alternative, using thedivmod() function to compute quotient and modulo together:

  1. Compute quotient and remainder at the same time:

    >>> total_seconds = 7385  >>> hours, remaining_seconds = divmod(total_seconds, 3600)
  2. Compute quotient and remainder again:

    >>> minutes, seconds = divmod(remaining_seconds, 60)  >>> hours, minutes, seconds  (2, 3, 5)

Doing true division

Performing a true division calculation gives a floating-point approximation as the result. For example, about how many hours is 7,385 seconds? Here’s736805 using the true division operator:

>>> total_seconds = 7385  >>> hours = total_seconds / 3600  >>> round(hours, 4)  2.0514

We provided two integer values, but got a floating-point exact result. Consistent with our previous recipe, when using floating-point values, we rounded the result to avoid having to look at tiny error digits.

Rational fraction calculations

We can do division usingFraction objects and integers. This forces the result to be a mathematically exact rational number:

  1. Create at least oneFraction value:

    >>> from fractions import Fraction  >>> total_seconds = Fraction(7385)
  2. Use theFraction value in a calculation. Any integer will be promoted to aFraction:

    >>> hours = total_seconds / 3600  >>> hours  Fraction(1477, 720)

    The denominator of 720 doesn’t seem too meaningful. Working with fractions like this requires a bit of finesse to find useful denominators that makes sense to people. Otherwise, converting to a floating-point value can be useful.

  3. If necessary, convert the exactFraction into a floating-point approximation:

    >>> round(float(hours), 4)  2.0514

First, we created aFraction object for the total number of seconds. When we do arithmetic on fractions, Python will promote any integers toFraction objects; this promotion means that the math is done as precisely as possible.

1.2.3How it works...

Python has two division operators:

  • The/ true division operator produces a true, floating-point result. It does this even when the two operands are integers. This is an unusual operator in this respect. All other operators preserve the type of the data. The true division operation – when applied to integers – produces a float result.

  • The// truncated division operator always produces a truncated result. For two integer operands, this is the truncated quotient. When floating-point operands are used, this is a truncated floating-point result:

    >>> 7358.0 // 3600.0  2.0

1.2.4See also

1.3String parsing with regular expressions

How do we decompose a complex string? What if we have complex, tricky punctuation? Or—worse yet—what if we don’t have punctuation, but have to rely on patterns of digits to locate meaningful information?

1.3.1Getting ready

The easiest way to decompose a complex string is by generalizing the string into a pattern and then writing a regular expression that describes that pattern.

There are limits to the patterns that regular expressions can describe. When we’re confronted with deeply nested documents in a language like HTML, XML, or JSON, we often run into problems and be prohibited from using regular expressions.

There module contains all of the various classes and functions we need to create and use regular expressions.

Let’s say that we want to decompose text from a recipe website. Each line looks like this:

>>> ingredient = "Kumquat: 2 cups"

We want to separate the ingredient from the measurements.

1.3.2How to do it...

To write and use regular expressions, we often do this:

  1. Generalize the example. In our case, we have something that we can generalize as:

    (ingredient words): (amount digits) (unit words)
  2. We’ve replaced literal text with a two-part summary: what it means and how it’s represented. For example,ingredient is represented as words, whileamount is represented as digits. Import there module:

    >>> import re
  3. Rewrite the pattern intoregular expression(RE) notation:

    >>> pattern_text = r’([\w\s]+):\s+(\d+)\s+(\w+)’

    We’ve replaced representation hints such asingredient words, a mixture of letters and spaces, with[\w\s]+. We’ve replacedamount digits with\d+. And we’ve replacedsingle spaceswith\s+ to allow one or more spaces to be used as punctuation. We’ve left the colon in place because, in regular expression notation, a colon matches itself.

    For each of the fields of data, we’ve used() to capture the data matching the pattern. We didn’t capture the colon or the spaces because we don’t need the punctuation characters.

    REs typically use a lot of\ characters. To make this work out nicely in Python, we almost always userawstrings. Ther’ tells Python not to look at the\ characters and not to replace them with special characters that aren’t on our keyboards.

  4. Compile thepattern:

    >>> pattern = re.compile(pattern_text)
  5. Match the pattern against the input text. If the input matches the pattern, we’ll get amatch object that shows details of the substring that matched:

    >>> match = pattern.match(ingredient)  >>> match is None  False  >>> match.groups()  (’Kumquat’, ’2’, ’cups’)
  6. Extract the named groups of characters from thematch object:

    >>> match.group(1)  ’Kumquat’  >>> match.group(2)  ’2’  >>> match.group(3)  ’cups’

Each group is identified by the order of the capture() portions of the regular expression. This gives us a tuple of the different fields captured from the string. We’ll return to the use of the tuple data structure in theUsing tuples of items recipe. This can be confusing in more complex regular expressions; there is a way to provide a name, instead of the numeric position, to identify a capture group.

1.3.3How it works...

There are a lot of different kinds of string patterns that we can describe with regular expressions.

We’ve shown a number of character classes:

  • \w matches any alphanumeric character (a to z, A to Z, 0 to 9).

  • \d matches any decimal digit.

  • \s matches any space or tab character.

These classes also have inverses:

  • \W matches any character that’s not a letter or a digit.

  • \D matches any character that’s not a digit.

  • \S matches any character that’s not some kind of space or tab.

Many characters match themselves. Some characters, however, have a special meaning, and we have to use\ to escape from that special meaning:

  • We saw that+ as a suffix means to match one or more of the preceding patterns.\d+ matches one or more digits. To match an ordinary+, we need to use\+.

  • We also have* as a suffix, which matches zero or more of the preceding patterns.\w* matches zero or more characters. To match a*, we need to use\*.

  • We have? as a suffix, which matches zero or one of the preceding expressions. This character is used in other places, and has a different meaning in the other context. We’ll see it used in?P<name>...)|, where it is inside \verb|)— to define special properties for the grouping.

  • The. character matches any single character. To match a. specifically, we need to use\..

We can create our own unique sets of characters using[] to enclose the elements of the set. We might have something like this:

(?P<name>\w+)\s*[=:]\s*(?P<value>.*)

This has a\w+ to match any number of alphanumeric characters. This will be collected into a group calledname. It uses\s* to match an optional sequence of spaces. It matches any character in the set[=:]. Exactly one of the two characters in this set must be present. It uses\s* again to match an optional sequence of spaces. Finally, it uses.* to match everything else in the string. This is collected into a group namedvalue.

We can use this to parse strings, like this:

size = 12  weight: 14

By being flexible with the punctuation, we can make a program easier to use. We’ll tolerate any number of spaces, and either an= or a: as a separator.

1.3.4There’s more...

A long regular expression can be awkward to read. We have a clever Pythonic trick for presenting an expression in a way that’s much easier to read:

>>> ingredient_pattern = re.compile(  ... r’(?P<ingredient>[\w\s]+):\s+’ # name of the ingredient up to the ":"  ... r’(?P<amount>\d+)\s+’ # amount, all digits up to a space  ... r’(?P<unit>\w+)’ # units, alphanumeric characters  ... )

This leverages three syntax rules:

  • A statement isn’t finished until the() characters match.

  • Adjacent string literals are silently concatenated into a single long string.

  • Anything between# and the end of the line is a comment, and is ignored.

We’ve put Python comments after the important clauses in our regular expression. This can help us understand what we did, and perhaps help us diagnose problems later.

We can also use the regular expression’s ”verbose” mode to add gratuitous whitespace and comments inside a regular expression string. To do this, we must usere.X as an option when compiling a regular expression to make whitespace and comments possible. This revised syntax looks like this:

>>> ingredient_pattern_x = re.compile(r’’’  ... (?P<ingredient>[\w\s]+):\s+ # name of the ingredient up to the ":"  ... (?P<amount>\d+)\s+ # amount, all digits up to a space  ... (?P<unit>\w+) # units, alphanumeric characters  ... ’’’, re.X)

We can either break the pattern up into separate string components, or make use of extended syntax to make the regular expression more readable. The benefit of providing names shows up when we use thegroupdict() method of thematch object to extract parsed values by the name associated with the pattern being captured.

1.3.5See also

1.4Building complicated strings with f-strings

Creating complex strings is, in many ways, the polar opposite of parsing a complex string. We generally use a template with substitution rules to put data into a more complex format.

1.4.1Getting ready

Let’s say we have pieces of data that we need to turn into a nicely formatted message. We might have data that includes the following:

>>> id = "IAD"  >>> location = "Dulles Intl Airport"  >>> max_temp = 32  >>> min_temp = 13  >>> precipitation = 0.4

And we’d like a line that looks like this:

IAD : Dulles Intl Airport : 32 / 13 / 0.40

1.4.2How to do it...

  1. Create an f-string for the result, replacing all of the data items with placeholders. Inside each placeholder, put a variable name (or an expression.) Note that the string uses the prefix off’. This prefix creates a sophisticated string object where values are interpolated into the template when the string is used:

    f’{id} : {location} : {max_temp} / {min_temp} / {precipitation}’
  2. For each name or expression, an optional data type can be appended to the names in the template string. The basic data type codes are:

    • s for string

    • d for decimal number

    • f for floating-point number

    It would look like this:

    f’{id:s} : {location:s} : {max_temp:d} / {min_temp:d} / {precipitation:f}’

    Because the book’s margins are narrow, the string has been broken to

    fit on the page. It’s a single (very wide) line of code.

  3. Add length information where required. Length is not always required, and in some cases, it’s not even desirable. In this example, though, the length information ensures that each message has a consistent format. For strings and decimal numbers, prefix the format with the length like this:19s or3d. For floating-point numbers, use a two-part prefix like5.2f to specify the total length of five characters, with two to the right of the decimal point. Here’s the whole format:

    >>> f’{id:3s} : {location:19s} : {max_temp:3d} / {min_temp:3d} / {precipitation:5.2f}’  ’IAD : Dulles Intl Airport :  32 /  13 /  0.40’

1.4.3How it works...

F-strings can do a lot of relatively sophisticated string assembly by interpolating data into a template. There are a number of conversions available.

We’ve seen three of the formatting conversions—s,d,f—but there are many others. Details can be found in theFormatted string literalssection of thePython Standard Library:https://docs.python.org/3/reference/lexical_analysis.html\#formatted-string-literals.

Here are some of the format conversions we might use:

  • b is for binary, base 2.

  • c is for Unicode character. The value must be a number, which is converted into a character. Often, we use hexadecimal numbers for these characters, so you might want to try values such as 0x2661 through 0x2666 to see interesting Unicode glyphs.

  • d is for decimal numbers.

  • E ande are for scientific notations. 6.626E-34 or 6.626e-34, depending on whichE ore character is used.

  • F andf are for floating-point. Fornot a number, thef format shows lowercasenan; theF format shows uppercaseNAN.

  • G andg are for general use. This switches automatically betweenE andF (ore andf) to keep the output in the given sized field. For a format of20.5G, up to 20-digit numbers will be displayed usingF formatting. Larger numbers will useE formatting.

  • n is for locale-specific decimal numbers. This will insert , or . characters, depending on the current locale settings. The default locale may not have 1,000 separators defined. For more information, see the locale module.

  • o is for octal, base 8.

  • s is for string.

  • X andx are for hexadecimal, base 16. The digits include uppercase A-F and lowercase a-f, depending on whichX orx format character is used.

  • % is for percentage. The number is multiplied by 100 and the output includes a% character.

We have a number of prefixes we can use for these different types. The most common one is the length. We might use{name:5d} to put in a 5-digit number. There are several prefixes for the preceding types:

  • Fill and alignment: We can specify a specific filler character (space is the default) and an alignment. Numbers are generally aligned to the right and strings to the left. We can change that using<,>, or^. This forces left alignment, right alignment, or centering, respectively. There’s a peculiar= alignment that’s used to put padding after a leading sign.

  • Sign: The default rule is a leading negative sign where needed. We can use+ to put a sign on all numbers,- to put a sign only on negative numbers, and a space to use a space instead of a plus for positive numbers. In scientific output, we often use{value:5.3f}. The space makes sure that room is left for the sign, ensuring that all the decimal points line up nicely.

  • Alternate form: We can use the# to get an alternate form. We might have something like{0:#x},{0:#o}, or{0:#b} to get a prefix on hexadecimal, octal, or binary values. With a prefix, the numbers will look like0xnnn,0onnn, or0bnnn. The default is to omit the two-character prefix.

  • Leading zero: We can include0 to get leading zeros to fill in the front of a number. Something like{code:08x} will produce a hexadecimal value with leading zeroes to pad it out to eight characters.

  • Width and precision: For integer values and strings, we only provide the width. For floating-point values, we often providewidth.precision.

There are some times when we won’t use a{name:format} specification. Sometimes, we’ll need to use a{name!conversion} specification. There are only three conversions available:

  • {name!r} shows the representation that would be produced byrepr(name).

  • {name!s} shows the string value that would be produced bystr(name); this is the default behavior if you don’t specify any conversion. Using!s explicitly lets you add string-type format specifiers.

  • {name!a} shows the ASCII value that would be produced byascii(name).

  • Additionally, there’s a handy debugging format specifier available. We can include a trailing equals sign,=, to get a handy dump of a variable or expression. The following example uses both forms:

    >>> value = 2**12-1  >>> f’{value=} {2**7+1=}’  ’value=4095 2**7+1=129’

The f-string showed the value of the variable namedvalue and the result of an expression,2**7+1.

InChapter 7, we’ll leverage the idea of the{name!r} format specification to simplify displaying information about related objects.

1.4.4There’s more...

The f-string processing relies on the stringformat() method. We can leverage this method and the relatedformat_map() method for cases where we have more complex data structures.

Looking forward toChapter 5, we might have a dictionary where the keys are simple strings that fit with theformat_map() rules:

>>> data = dict(  ... id=id, location=location, max_temp=max_temp,  ... min_temp=min_temp, precipitation=precipitation  ... )  >>> ’{id:3s} : {location:19s} : {max_temp:3d} / {min_temp:3d} / {precipitation:5.2f}’.format_map(data)  ’IAD : Dulles Intl Airport :  32 /  13 /  0.40’

We’ve created a dictionary object, data, that contains a number of values with keys that are valid Python identifiers:id,location,max_temp,min_temp, andprecipitation. We can then use this dictionary with theformat_map() method to extract values from the dictionary using the keys.

Note that the formatting template here isnotan f-string. It doesn’t have thef" prefix. Instead of using the automatic formatting features of an f-string, we’ve done the interpolation ”the hard way” using theformat_map() method of an f-string.

1.4.5See also

1.5Building complicated strings from lists of strings

How can we make complicated changes to an immutable string? Can we assemble a string from individual characters?

In most cases, the recipes we’ve already seen give us a number of tools for creating and modifying strings. There are yet more ways in which we can tackle the string manipulation problem. In this recipe, we’ll look at using alist object as a way to decompose and rebuild a string. This will dovetail with some of the recipes inChapter 4.

1.5.1Getting ready

Here’s a string that we’d like to rearrange:

>>> title = "Recipe 5: Rewriting an Immutable String"

We’d like to do two transformations:

  • Remove the part before:.

  • Replace the punctuation with_ and make all the characters lowercase.

We’ll make use of thestring module:

>>> from string import whitespace, punctuation

This has two important constants:

  • string.whitespace lists all of the whitespace characters that are also part of ASCII, including space and tab.

  • string.punctuation lists punctuation marks that are also part of ASCII. Unicode has a large domain of punctuation marks. This is a widely used subset.

1.5.2How to do it...

We can work with a string exploded into a list. We’ll look at lists in more depth inChapter 4:

  1. Explode the string into alist object:

    >>> title_list = list(title)
  2. Find the partition character. Theindex() method for a list has the same semantics as theindex() method has for a string. It locates the position with the given value:

    >>> colon_position = title_list.index(’:’)
  3. Delete the characters that are no longer needed. Thedel statement can remove items from a list. Unlike strings, lists are mutable data structures:

    >>> del title_list[:colon_position+1]
  4. Replace punctuation by stepping through each position. In this case, we’ll use afor statement to visit every index in the string:

    >>> for position in range(len(title_list)):  ...     if title_list[position] in whitespace+punctuation:  ...         title_list[position]= ’_’
  5. The expressionrange(len(title_list)) generates all of the values between 0 andlen(title_list)-1. This assures us that the value of position will be each value index in the list. Join the list of characters to create a new string. It seems a little odd to use a zero-length string,’’, as a separator when concatenating strings together. However, it works perfectly:

    >>> title = ’’.join(title_list)  >>> title  ’_Rewriting_an_Immutable_String’

We assigned the resulting string back to the original variable. The original string object, which had been referred to by that variable, is no longer needed: it’s automatically removed from memory (this is known asgarbage collection). The new string object replaces the value of the variable.

1.5.3How it works...

This is a change in representation trick. Since a string is immutable, we can’t update it. We can, however, convert it into a mutable form; in this case, a list. We can make whatever changes are required to the mutable list object. When we’re done, we can change the representation from a list back to a string and replace the original value of the variable.

Lists provide some features that strings don’t have. Conversely, strings provide a number of features lists don’t have. As an example, we can’t convert a list into lowercase the way we can convert a string.

There’s an important trade-off here:

  • Strings are immutable, which makes them very fast. Strings are focused on Unicode characters. When we look at mappings and sets, we can use strings as keys for mappings and items in sets because the value is immutable.

  • Lists are mutable. Operations are slower. Lists can hold any kind of item. We can’t use a list as a key for a mapping or an item in a set because the list value could change.

Strings and lists are both specialized kinds of sequences. Consequently, they have a number of common features. The basic item indexing and slicing features are shared. Similarly, a list uses the same kind of negative index values that a string does: the expressionlist[-1] is the last item in a list object.

We’ll return to mutable data structures inChapter 4.

1.5.4See also

1.6Using the Unicode characters that aren’t on our keyboards

A big keyboard might have almost 100 individual keys. Often, fewer than 50 of these keys are letters, numbers, and punctuation. At least a dozen arefunction keys that do things other than simplyinsertletters into a document. Some of the keys are different kinds ofmodifiersthat are meant to be used in conjunction with another key—for example, we might haveShift,Ctrl,Option, andCommand.

Most operating systems will accept simple key combinations that create about 100 or so characters. More elaborate key combinations may create another 100 or so less popular characters. This isn’t even close to covering the vast domain of characters from the world’s alphabets. And there are icons, emojis, and dingbats galore in our computer fonts. How do we get to all of those glyphs?

1.6.1Getting ready

Python works in Unicode. There are thousands of individual Unicode characters available.

We can see all the available characters athttps://en.wikipedia.org/wiki/List_of_Unicode_characters, as well as athttp://www.unicode.org/charts/.

We’ll need the Unicode character number. We may also want the Unicode character name.

A given font on our computer may not be designed to provide glyphs for all of those characters. In particular, Windows computer fonts may have trouble displaying some of these characters. Using the following Windows command to change to code page 65001 is sometimes necessary:

chcp 65001

Linux and macOS rarely have problems with Unicode characters.

1.6.2How to do it...

Python usesescape sequencesto extend the ordinary characters we can type to cover the vast space of Unicode characters. Each escape sequence starts with a\ character. The next character tells us exactly which of the Unicode characters to create. Locate the character that’s needed. Get the name or the number. The numbers are always given as hexadecimal, base 16. Websites describing Unicode often write the character asU+2680. The name might beDIE FACE-1. Use\unnnn with up to a four-digit number,nnnn. Or, use\N{name} with the spelled-out name. If the number is more than four digits, use\Unnnnnnnn with the number padded out to exactly eight digits:

>>> ’You Rolled \u2680’  ’You Rolled ’  >>> ’You drew \U0001F000’  ’You drew ’  >>> ’Discard \N{MAHJONG TILE RED DRAGON}’  ’Discard ’

Yes, we can include a wide variety of characters in Python output. To place a\ in the string without the following characters being part of an escape sequence, we need to use\\. For example, we might need this for Windows file paths.

1.6.3How it works...

Python uses Unicode internally. The 128 or so characters we can type directly using the keyboard all have handy internal Unicode numbers.

When we write:

’HELLO’

Python treats it as shorthand for this:

’\u0048\u0045\u004c\u004c\u004f’

Once we get beyond the characters on our keyboards, the remaining thousands of characters are identified only by their number.

When the string is being compiled by Python,\uxxxx,\Uxxxxxxxx, and\N{name} are all replaced by the proper Unicode character. If we have something syntactically wrong—for example,\N{name with no closing}—we’ll get an immediate error from Python’s internal syntax checking.

Regular expressions use a lot of\ characters and that we specifically do not want Python’s normal compiler to touch them; we used ther’ prefix on a regular expression string to prevent\ from being treated as an escape and possibly converted into something else. To use the full domain of Unicode characters, we cannot avoid using\ as an escape.

What if we need to use Unicode in a regular expression? We’ll need to use\\ all over the place in the regular expression. We might see something like this:’\\w+[\u2680\u2681\u2682\u2683\u2684\u2685]\\d+’.

We couldn’t use ther’ prefix on the string because we needed to have the Unicode escapes processed. This forced us to use\\ for elements of the regular expression. We used\uxxxx for the Unicode characters that are part of the pattern. Python’s internal compiler will replace\uxxxx with Unicode characters and\\w will become the required\w internally.

When we look at a string at the>>> prompt, Python will display the string in its canonical form. Python prefers to display strings with as a delimiter, using" when the string contains a. We can use either or" for a string delimiter when writing code. Python doesn’t generally display raw strings; instead, it puts all of the necessary escape sequences back into the string:

>>> r"\w+"  ’\\w+’

We provided a string in raw form. Python displayed it in canonical form.

1.6.4See also

1.7Encoding strings – creating ASCII and UTF-8 bytes

Our computer files are bytes. When we upload or download from the internet, the communication works in bytes. A byte only has 256 distinct values. Our Python characters are Unicode. There are a lot more than 256 Unicode characters.

How do we map Unicode characters to bytes to write to a file or for transmission?

1.7.1Getting ready

Historically, a character occupied 1 byte. Python leverages the old ASCII encoding scheme for bytes; this sometimes leads to confusion between bytes and text strings of Unicode characters.

Unicode characters are encoded into sequences of bytes. There are a number of standardized encodings and a number of non-standard encodings.

Plus, there also are some encodings that only work for a small subset of Unicode characters. We try to avoid these, but there are some situations where we’ll need to use a subset encoding scheme.

Unless we have a really good reason not to, we almost always use UTF-8 encoding for Unicode characters. Its main advantage is that it’s a compact representation of the Latin alphabet, which is used for English and a number of European languages.

Sometimes, an internet protocol requires ASCII characters. This is a special case that requires some care because the ASCII encoding can only handle a small subset of Unicode characters.

1.7.2How to do it...

Python will generally use our OS’s default encoding for files and internet traffic. The details are unique to each OS:

  1. We can make a general setting using thePYTHONIOENCODING environment variable. We set this outside of Python to ensure that a particular encoding is used everywhere. When using Linux or macOS, use the shell’sexport statement to set the environment variable. For Windows, use theset command, or the PowerShellSet-Item cmdlet. For Linux, it looks like this:

    (cookbook3) % export PYTHONIOENCODING=UTF-8
  2. Run Python:

    (cookbook3) % python
  3. We sometimes need to make specific settings when we open a file inside our script. We’ll return to this topic inChapter 11. Open the file with a given encoding. Read or write Unicode characters to the file:

    >>> with open(’some_file.txt’, ’w’, encoding=’utf-8’) as output:  ...     print(’You drew \U0001F000’, file=output)  >>> with open(’some_file.txt’, ’r’, encoding=’utf-8’) as input:  ...     text = input.read()  >>> text  ’You drew ’

We can also manually encode characters, in the rare case that we need to open a file in bytes mode; if we use a mode ofwb, we’ll also need to use manual encoding of each string:

>>> string_bytes = ’You drew \U0001F000’.encode(’utf-8’)  >>> string_bytes  b’You drew \xf0\x9f\x80\x80’

We can see that a sequence of bytes (\xf0\x9f\x80\x80) was used to encode a single Unicode character,U+1F000,PIC.

1.7.3How it works...

Unicode defines a number of encoding schemes. While UTF-8 is the most popular, there is also UTF-16 and UTF-32. The number is the typical number of bits per character. A file with 1,000 characters encoded in UTF-32 would be 4,000 8-bit bytes. A file with 1,000 characters encoded in UTF-8 could be as few as 1,000 bytes, depending on the exact mix of characters. In UTF-8 encoding, characters with Unicode numbers above U+007F require multiple bytes.

Various OSes have their own coding schemes. macOS files can be encoded in Mac Roman or Latin-1. Windows files might use CP1252 encoding.

The point with all of these schemes is to have a sequence of bytes that can be mapped to a Unicode character and—going the other way—a way to map each Unicode character to one or more bytes. Ideally, all of the Unicode characters are accounted for. Pragmatically, some of these coding schemes are incomplete.

The historical form of ASCII encoding can only represent about 100 of the Unicode characters as bytes. It’s easy to create a string that cannot be encoded using the ASCII scheme.

Here’s what the error looks like:

>>> ’You drew \U0001F000’.encode(’ascii’)  Traceback (most recent call last):  ...  UnicodeEncodeError: ’ascii’ codec can’t encode character ’\U0001f000’ in position 9: ordinal not in range(128

We may see this kind of error when we accidentally open a file with an encoding that’s not the widely used standard of UTF-8. When we see this kind of error, we’ll need to change our processing to select the encoding actually used to create the file. It’s almost impossible to guess what encoding was used, so some research may be required to locate metadata about the file that states the encoding.

Bytes are often displayed using printable characters. We’ll seeb’hello’ as shorthand for a five-byte value. The letters are chosen using the old ASCII encoding scheme, where byte values from 0x20 to 0x7F will be shown as characters, and outside this range, more complex-looking escapes will be used.

This use of characters to represent byte values can be confusing. The prefix ofb’ is our hint that we’re looking at bytes, not proper Unicode characters.

1.7.4See also

1.8Decoding bytes – how to get proper characters from some bytes

How can we work with files that aren’t properly encoded? What do we do with files written in ASCII encoding?

A download from the internet is almost always in bytes—not characters. How do we decode the characters from that stream of bytes?

Also, when we use the subprocess module, the results of an OS command are in bytes. How can we recover proper characters?

Much of this is also relevant to the material inChapter 11. We’ve included this recipe here because it’s the inverse of the previous recipe,Encoding strings –creating ASCII and UTF-8 bytes.

1.8.1Getting ready

Let’s say we’re interested in offshore marine weather forecasts. Perhaps this is because we are departing theChesapeake Bayfor theCaribbean.

Are there any special warnings coming from theNational Weather Services office in Wakefield, Virginia?

Here’s the link:https://forecast.weather.gov/product.php?site=AKQ&product=SMW&issuedby=AKQ.

We can download this with Python’surllib module:

>>> import urllib.request  >>> warnings_uri = (  ...     ’https://forecast.weather.gov/’  ...     ’product.php?site=AKQ&product=SMW&issuedby=AKQ’  ... )  >>> with urllib.request.urlopen(warnings_uri) as source:  ...     forecast_text = source.read()

Note that we’ve enclosed the URI string in() and broken it into two separate string literals. Python will concatenate these two adjacent literals into a single string. We’ll look at this in some depth inChapter 2.

As an alterative, we can use programs likecurl orwget to get this. At the OS Terminal prompt, we might run the following (long) command:

(cookbook3) % curl ’https://forecast.weather.gov/product.php?site=AKQ&product=SMW&issuedby=AKQ’ -o AKQ.html

Typesetting this book tends to break the command onto many lines. It’s really one very long line.

The code repository includes a sample file,ch01/Text Products for SMW Issuedby AKQ.html.

Theforecast_text value is a stream of bytes. It’s not a proper string. We can tell because it starts like this:

>>> forecast_text[:80]  b’<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x’

The data goes on for a while, providing details from the web page. Because the displayed value starts withb’, it’s bytes, not proper Unicode characters. It was probably encoded with UTF-8, which means some characters could have weird-looking\xnn escape sequences instead of proper characters. We want to have the proper characters.

While this data has many easy-to-read characters, theb’ prefix shows that it’s a collection of byte values, not proper text. Generally, a bytes object behaves somewhat like a string object. Sometimes, we can work with bytes directly. Most of the time, we’ll want to decode the bytes and create proper Unicode characters from them.

1.8.2How to do it...

  1. Determine the coding scheme if possible. In order to decode bytes to create proper Unicode characters, we need to know what encoding scheme was used. When we read XML documents, there’s a big hint provided within the document:

    <?xml version="1.0" encoding="UTF-8"?>

    When browsing web pages, there’s often a header containing this information:

    Content-Type: text/html; charset=ISO-8859-4

    Sometimes, an HTML page may include this as part of the header:

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    In other cases, we’re left to guess. In the case of US weather data, a good first guess is UTF-8. Another good guess is ISO-8859-1. In some cases, the guess will depend on the language.

  2. Thecodecs — Codec registry and base classessection of thePythonStandard Librarylists the standard encodings available. Decode the data:

    >>> document = forecast_text.decode("UTF-8")  >>> document[:80]  ’<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x’

    Theb’ prefix is no longer used to show that these are bytes. We’ve created a proper string of Unicode characters from the stream of bytes.

  3. If this step fails with an exception, we guessed wrong about the encoding. We need to try another encoding in order to parse the resulting document.

Since this is an HTML document, we should useBeautiful Soupto extract the data. Seehttp://www.crummy.com/software/BeautifulSoup/.

We can, however, extract one nugget of information from this document without completely parsing the HTML:

>>> import re  >>> content_pattern = re.compile(r"// CONTENT STARTS(.*?)// CONTENT ENDS", re.MULTILINE | re.DOTALL)  >>> content_pattern.search(document)  <re.Match object; span=(8530, 9113), match=’// CONTENT STARTS HERE -->\n\n<span0.4.8.3">

1.8.3How it works...

See theEncoding strings – creating ASCII and UTF-8 bytes recipe for more information on Unicode and the different ways that Unicode characters can be encoded into streams of bytes.

At the foundation of the OS, files and network connections are built up from bytes. It’s our software that decodes the bytes to discover the content. It might be characters, images, or sounds. In some cases, the default assumptions are wrong and we need to do our own decoding.

1.8.4See also

1.9Using tuples of items

What’s the best way to represent simple (x,y) and (r,g,b) groups of values? How can we keep things that are pairs, such as latitude and longitude, together?

1.9.1Getting ready

In theString parsing with regular expressions recipe, we skipped over an interesting data structure.

We had data that looked like this:

>>> ingredient = "Kumquat: 2 cups"

We parsed this into meaningful data using a regular expression, like this:

>>> import re  >>> ingredient_pattern = re.compile(r’(?P<ingredient>\w+):\s+(?P<amount>\d+)\s+(?P<unit>\w+)’)  >>> match = ingredient_pattern.match(ingredient)  >>> match.groups()  (’Kumquat’, ’2’, ’cups’)

The result is a tuple object with three pieces of data. There are lots of places where this kind of grouped data can come in handy.

1.9.2How to do it...

We’ll look at two aspects to this: putting things into tuples and getting things out of tuples.

Creating tuples

There are lots of places where Python creates tuples of data for us. In theGettingreadysection of theString parsing with regular expressions recipe, we showed you how a regular expressionmatch object will create a tuple of text that was parsed from a string.

We can create our own tuples, too. Here are the steps:

  1. Enclose the data in().

  2. Separate the items with,.

    >>> from fractions import Fraction  >>> my_data = (’Rice’, Fraction(1/4), ’cups’)

There’s an important special case for the one-tuple, or singleton. We have to include the, even when there’s only one item in the tuple:

>>> one_tuple = (’item’, )  >>> len(one_tuple)  1

The() characters aren’t always required. There are a few times where we can omit them. It’s not a good idea to omit them.

It’s the comma that creates a tuple of values. This means we can see funny things when we have an extra comma:

>>> 355,  (355,)

The comma after 355 turns the value into a singleton tuple.

We can also create a tuple by conversion from another sequence. For example,tuple([355]) creates a singleton tuple from a singleton list.

Extracting items from a tuple

The idea of a tuple is to be a container with a number of items that’s fixed by the problem domain: for example, for (red, green, blue) color numbers, the number of items is always three.

In our example, we’ve got an ingredient, and amount, and units. This must be a three-item collection. We can look at the individual items in two ways:

  • By index position; that is, positions are numbered starting with zero from the left:

    >>> my_data[1]  Fraction(1, 4)
  • Using multiple assignment:

    >>> ingredient, amount, unit =  my_data  >>> ingredient  ’Rice’  >>> unit  ’cups’

Tuples—like strings—are immutable. We can’t change the individual items inside a tuple. We use tuples when we want to keep the data together.

1.9.3How it works...

Tuples are one example of the more generalSequence class. We can do a few things with sequences.

Here’s an example tuple that we can work with:

>>> t = (’Kumquat’, ’2’, ’cups’)

Here are some operations we can perform on this tuple:

  • How many items int?

    >>> len(t)  3
  • How many times does a particular value appear int?

    >>> t.count(’2’)  1
  • Which position has a particular value?

    >>> t.index(’cups’)  2  >>> t[2]  ’cups’
  • When an item doesn’t exist, we’ll get an exception:

    >>> t.index(’Rice’)  Traceback (most recent call last):  ...  ValueError: tuple.index(x): x not in tuple
  • Does a particular value exist?

    >>> ’Rice’ in t  False

1.9.4There’s more...

A tuple, like a string, is a sequence of items. In the case of a string, it’s a sequence of characters. In the case of a tuple, it’s a sequence of many things. Because they’re both sequences, they have some common features. We’ve noted that we can pluck out individual items by their index position. We can use theindex() method to locate the position of an item.

The similarities end there. A string has many methods it can use to create a new string that’s a transformation of a string, plus methods to parse strings, plus methods to determine the content of the strings. A tuple doesn’t have any of these bonus features. It’s—perhaps—the simplest possible data structure.

1.9.5See also

1.10Using NamedTuples to simplify item access in tuples

When we worked with tuples, we had to remember the positions as numbers. When we use a (r,g,b) tuple to represent a color, can we use ”red” instead of zero, ”green” instead of 1, and ”blue” instead of 2?

1.10.1Getting ready

Let’s continue looking at items in recipes. The regular expression for parsing the string had three attributes:ingredient,amount, andunit. We used the following pattern with names for the various substrings:

r’(?P<ingredient>\w+):\s+(?P<amount>\d+)\s+(?P<unit>\w+)’)

The resulting data tuple looked like this:

>>> item = match.groups()  >>> item  (’Kumquat’, ’2’, ’cups’)

While the matching betweeningredient,amount, andunit is pretty clear, using something like the following isn’t ideal. What does1 mean? Is it really the quantity?

>>> from fractions import Fraction  >>> Fraction(item[1])  Fraction(2, 1)

We want to define tuples with names, as well as positions.

1.10.2How to do it...

  1. We’ll use theNamedTuple class definition from thetyping package:

    >>> from typing import NamedTuple
  2. With this base class definition, we can define our own unique tuples, with names for the items:

    >>> class Ingredient(NamedTuple):  ...     ingredient: str  ...     amount: str  ...     unit: str
  3. Now, we can create an instance of this unique kind of tuple by using the classname:

    >>> item_2 = Ingredient(’Kumquat’, ’2’, ’cups’)
  4. When we want a value from the tuple, we can use a name instead of the position:

    >>> Fraction(item_2.amount)  Fraction(2, 1)  >>> f"Use {item_2.amount} {item_2.unit} fresh {item_2.ingredient}"  ’Use 2 cups fresh Kumquat’

1.10.3How it works...

TheNamedTuple class definition introduces a core concept fromChapter 7. We’ve extended the base class definition to add unique features for our application. In this case, we’ve named the three attributes eachIngredient tuple must contain.

Because a subclass ofNamedTuple class is a tuple, the order of the attribute names is fixed. We can use a reference like the expressionitem_2[0] as well as the expressionitem_2.ingredient. Both names refer to the item in index 0 of the tuple,item_2.

The core tuple types can be called ”anonymous tuples” or maybe ”index-only tuples.” This can help to distinguish them from the more sophisticated ”named tuples” introduced through thetyping module.

Tuples are very useful as tiny containers of closely related data. Using theNamedTuple class definition makes them even easier to work with.

1.10.4There’s more...

We can have a mixed collection of values in a tuple or a named tuple. We need to perform conversion before we can build the tuple. It’s important to remember that a tuple cannot ever be changed. It’s an immutable object, similar in many ways to the way strings and numbers are immutable.

For example, we might want to work with amounts that are exact fractions. Here’s a more sophisticated definition:

>>> from typing import NamedTuple  >>> from fractions import Fraction  >>> class IngredientF(NamedTuple):  ...     ingredient: str  ...     amount: Fraction  ...     unit: str

These objects require some care to create. If we’re using a bunch of strings, we can’t simply build this object from three string values; we need to convert the amount into aFraction instance. Here’s an example of creating an item using aFraction conversion:

>>> item_3 = IngredientF(’Kumquat’, Fraction(’2’), ’cups’)

This tuple has a more useful value for the amount of each ingredient. We can now do mathematical operations on the amounts:

>>> f’{item_3.ingredient} doubled: {item_3.amount * 2}’  ’Kumquat doubled: 4’

It’s very handy to explicitly state the data type within theNamedTuple class definition. It turns out Python doesn’t use the type information directly. Other tools, for example,mypy, can check the type hints in aNamedTuple against the operations in the rest of the code to be sure they agree.

1.10.5See also

  • We’ll look at class definitions inChapter 7.

Join our community Discord space

Join our Python Discord workspace to discuss and find out more about the book:https://packt.link/dHrHU

PIC

Left arrow icon

Page1 of 11

Right arrow icon
Download code iconDownload Code

Key benefits

  • New chapters on type matching, data visualization, dependency management, and more
  • Comprehensive coverage of Python 3.12 with updated recipes and techniques
  • Provides practical examples and detailed explanations to solve real-world problems efficiently

Description

Python is the go-to language for developers, engineers, data scientists, and hobbyists worldwide. Known for its versatility, Python can efficiently power applications, offering remarkable speed, safety, and scalability. This book distills Python into a collection of straightforward recipes, providing insights into specific language features within various contexts, making it an indispensable resource for mastering Python and using it to handle real-world use cases.The third edition of Modern Python Cookbook provides an in-depth look into Python 3.12, offering more than 140 new and updated recipes that cater to both beginners and experienced developers. This edition introduces new chapters on documentation and style, data visualization with Matplotlib and Pyplot, and advanced dependency management techniques using tools like Poetry and Anaconda. With practical examples and detailed explanations, this cookbook helps developers solve real-world problems, optimize their code, and get up to date with the latest Python features.

Who is this book for?

This Python book is for web developers, programmers, enterprise programmers, engineers, and big data scientists. If you are a beginner, this book offers helpful details and design patterns for learning Python. If you are experienced, it will expand your knowledge base. Fundamental knowledge of Python programming and basic programming principles will be helpful

What you will learn

  • Master core Python data structures, algorithms, and design patterns
  • Implement object-oriented designs and functional programming features
  • Use type matching and annotations to make more expressive programs
  • Create useful data visualizations with Matplotlib and Pyplot
  • Manage project dependencies and virtual environments effectively
  • Follow best practices for code style and testing
  • Create clear and trustworthy documentation for your projects

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date :Jul 31, 2024
Length:818 pages
Edition :3rd
Language :English
ISBN-13 :9781835460757
Category :
Languages :

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Product Details

Publication date :Jul 31, 2024
Length:818 pages
Edition :3rd
Language :English
ISBN-13 :9781835460757
Category :
Languages :
Concepts :

Packt Subscriptions

See our plans and pricing
Modal Close icon
₹800billed monthly
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconSimple pricing, no contract
₹4500billed annually
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just ₹400 each
Feature tick iconExclusive print discounts
₹5000billed in 18 months
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just ₹400 each
Feature tick iconExclusive print discounts

Frequently bought together


Mastering Python Design Patterns
Mastering Python Design Patterns
Read more
May 2024296 pages
Full star icon4.3 (8)
eBook
eBook
₹799.99₹2382.99
₹2978.99
Python Real-World Projects
Python Real-World Projects
Read more
Sep 2023478 pages
Full star icon4.4 (5)
eBook
eBook
₹799.99₹2740.99
₹3425.99
Modern Python Cookbook
Modern Python Cookbook
Read more
Jul 2024818 pages
Full star icon4.9 (21)
eBook
eBook
₹799.99₹3276.99
₹4096.99
Stars icon
Total10,501.97
Mastering Python Design Patterns
₹2978.99
Python Real-World Projects
₹3425.99
Modern Python Cookbook
₹4096.99
Total10,501.97Stars icon

Table of Contents

19 Chapters
Chapter 1 Numbers, Strings, and TuplesChevron down iconChevron up icon
Chapter 1 Numbers, Strings, and Tuples
1.1 Choosing between float, decimal, and fraction
1.2 Choosing between true division and floor division
1.3 String parsing with regular expressions
1.4 Building complicated strings with f-strings
1.5 Building complicated strings from lists of strings
1.6 Using the Unicode characters that aren’t on our keyboards
1.7 Encoding strings – creating ASCII and UTF-8 bytes
1.8 Decoding bytes – how to get proper characters from some bytes
1.9 Using tuples of items
1.10 Using NamedTuples to simplify item access in tuples
Chapter 2 Statements and SyntaxChevron down iconChevron up icon
Chapter 2 Statements and Syntax
2.1 Writing Python script and module files – syntax basics
2.2 Writing long lines of code
2.3 Including descriptions and documentation
2.4 Writing better docstrings with RST markup
2.5 Designing complex if...elif chains
2.6 Saving intermediate results with the := ”walrus” operator
2.7 Avoiding a potential problem with break statements
2.8 Leveraging exception matching rules
2.9 Avoiding a potential problem with an except: clause
2.10 Concealing an exception root cause
2.11 Managing a context using the with statement
Chapter 3 Function DefinitionsChevron down iconChevron up icon
Chapter 3 Function Definitions
3.1 Function parameters and type hints
3.2 Designing functions with optional parameters
3.3 Using super flexible keyword parameters
3.4 Forcing keyword-only arguments with the * separator
3.5 Defining position-only parameters with the / separator
3.6 Picking an order for parameters based on partial functions
3.7 Writing clear documentation strings with RST markup
3.8 Designing recursive functions around Python’s stack limits
3.9 Writing testable scripts with the script-library switch
Chapter 4 Built-In Data Structures Part 1: Lists and SetsChevron down iconChevron up icon
Chapter 4 Built-In Data Structures Part 1: Lists and Sets
4.1 Choosing a data structure
4.2 Building lists – literals, appending, and comprehensions
4.3 Slicing and dicing a list
4.4 Shrinking lists – deleting, removing, and popping
4.5 Writing list-related type hints
4.6 Reversing a copy of a list
4.7 Building sets – literals, adding, comprehensions, and operators
4.8 Shrinking sets – remove(), pop(), and difference
4.9 Writing set-related type hints
Chapter 5 Built-In Data Structures Part 2: DictionariesChevron down iconChevron up icon
Chapter 5 Built-In Data Structures Part 2: Dictionaries
5.1 Creating dictionaries – inserting and updating
5.2 Shrinking dictionaries – the pop() method and the del statement
5.3 Writing dictionary-related type hints
5.4 Understanding variables, references, and assignment
5.5 Making shallow and deep copies of objects
5.6 Avoiding mutable default values for function parameters
Chapter 6 User Inputs and OutputsChevron down iconChevron up icon
Chapter 6 User Inputs and Outputs
6.1 Using the features of the print() function
6.2 Using input() and getpass() for user input
6.3 Debugging with f”{value=}” strings
6.4 Using argparse to get command-line input
6.5 Using invoke to get command-line input
6.6 Using cmd to create command-line applications
6.7 Using the OS environment settings
Chapter 7 Basics of Classes and ObjectsChevron down iconChevron up icon
Chapter 7 Basics of Classes and Objects
7.1 Using a class to encapsulate data and processing
7.2 Essential type hints for class definitions
7.3 Designing classes with lots of processing
7.4 Using typing.NamedTuple for immutable objects
7.5 Using dataclasses for mutable objects
7.6 Using frozen dataclasses for immutable objects
7.7 Optimizing small objects with __slots__
7.8 Using more sophisticated collections
7.9 Extending a built-in collection – a list that does statistics
7.10 Using properties for lazy attributes
7.11 Creating contexts and context managers
7.12 Managing multiple contexts with multiple resources
Chapter 8 More Advanced Class DesignChevron down iconChevron up icon
Chapter 8 More Advanced Class Design
8.1 Choosing between inheritance and composition – the ”is-a” question
8.2 Separating concerns via multiple inheritance
8.3 Leveraging Python’s duck typing
8.4 Managing global and singleton objects
8.5 Using more complex structures – maps of lists
8.6 Creating a class that has orderable objects
8.7 Deleting from a list of complicated objects
Chapter 9 Functional Programming FeaturesChevron down iconChevron up icon
Chapter 9 Functional Programming Features
9.1 Writing generator functions with the yield statement
9.2 Applying transformations to a collection
9.3 Using stacked generator expressions
9.4 Picking a subset – three ways to filter
9.5 Summarizing a collection – how to reduce
9.6 Combining the map and reduce transformations
9.7 Implementing “there exists” processing
9.8 Creating a partial function
9.9 Writing recursive generator functions with the yield from statement
Chapter 10 Working with Type Matching and AnnotationsChevron down iconChevron up icon
Chapter 10 Working with Type Matching and Annotations
10.1 Designing with type hints
10.2 Using the built-in type matching functions
10.3 Using the match statement
10.4 Handling type conversions
10.5 Implementing more strict type checks with Pydantic
10.6 Including run-time valid value checks
Chapter 11 Input/Output, Physical Format, and Logical LayoutChevron down iconChevron up icon
Chapter 11 Input/Output, Physical Format, and Logical Layout
11.1 Using pathlib to work with filenames
11.2 Replacing a file while preserving the previous version
11.3 Reading delimited files with the CSV module
11.4 Using dataclasses to simplify working with CSV files
11.5 Reading complex formats using regular expressions
11.6 Reading JSON and YAML documents
11.7 Reading XML documents
11.8 Reading HTML documents
Chapter 12 Graphics and Visualization with Jupyter LabChevron down iconChevron up icon
Chapter 12 Graphics and Visualization with Jupyter Lab
12.1 Starting a Notebook and creating cells with Python code
12.2 Ingesting data into a notebook
12.3 Using pyplot to create a scatter plot
12.4 Using axes directly to create a scatter plot
12.5 Adding details to markdown cells
12.6 Including Unit Test Cases in a Notebook
Chapter 13 Application Integration: ConfigurationChevron down iconChevron up icon
Chapter 13 Application Integration: Configuration
13.1 Finding configuration files
13.2 Using TOML for configuration files
13.3 Using Python for configuration files
13.4 Using a class as a namespace for configuration
13.5 Designing scripts for composition
13.6 Using logging for control and audit output
Chapter 14 Application Integration: CombinationChevron down iconChevron up icon
Chapter 14 Application Integration: Combination
14.1 Combining two applications into one
14.2 Combining many applications using the Command design pattern
14.3 Managing arguments and configuration in composite applications
14.4 Wrapping and combining CLI applications
14.5 Wrapping a program and checking the output
Chapter 15 TestingChevron down iconChevron up icon
Chapter 15 Testing
15.1 Using docstrings for testing
15.2 Testing functions that raise exceptions
15.3 Handling common doctest issues
15.4 Unit testing with the unittest module
15.5 Combining unittest and doctest tests
15.6 Unit testing with the pytest module
15.7 Combining pytest and doctest tests
15.8 Testing things that involve dates or times
15.9 Testing things that involve randomness
15.10 Mocking external resources
Chapter 16 Dependencies and Virtual EnvironmentsChevron down iconChevron up icon
Chapter 16 Dependencies and Virtual Environments
16.1 Creating environments using the built-in venv
16.2 Installing packages with a requirements.txt file
16.3 Creating a pyproject.toml file
16.4 Using pip-tools to manage the requirements.txt file
16.5 Using Anaconda and the conda tool
16.6 Using the poetry tool
16.7 Coping with changes in dependencies
Chapter 17 Documentation and StyleChevron down iconChevron up icon
Chapter 17 Documentation and Style
17.1 The bare minimum: a README.rst file
17.2 Installing Sphinx and creating documentation
17.3 Using Sphinx autodoc to create the API reference
17.4 Identifying other CI/CD tools in pyproject.toml
17.5 Using tox to run comprehensive quality checks
Other Books You May EnjoyChevron down iconChevron up icon
Other Books You May Enjoy
IndexChevron down iconChevron up icon
Index

Recommendations for you

Left arrow icon
Debunking C++ Myths
Debunking C++ Myths
Read more
Dec 2024226 pages
Full star icon5 (1)
eBook
eBook
₹799.99₹2382.99
₹2978.99
Go Recipes for Developers
Go Recipes for Developers
Read more
Dec 2024350 pages
eBook
eBook
₹799.99₹2382.99
₹2978.99
50 Algorithms Every Programmer Should Know
50 Algorithms Every Programmer Should Know
Read more
Sep 2023538 pages
Full star icon4.5 (68)
eBook
eBook
₹799.99₹2978.99
₹3723.99
₹3723.99
Asynchronous Programming with C++
Asynchronous Programming with C++
Read more
Nov 2024424 pages
Full star icon5 (1)
eBook
eBook
₹799.99₹2502.99
₹3127.99
Modern CMake for C++
Modern CMake for C++
Read more
May 2024504 pages
Full star icon4.7 (12)
eBook
eBook
₹799.99₹2978.99
₹3723.99
Learn Python Programming
Learn Python Programming
Read more
Nov 2024616 pages
Full star icon5 (1)
eBook
eBook
₹799.99₹2382.99
₹2978.99
Learn to Code with Rust
Learn to Code with Rust
Read more
Nov 202457hrs 40mins
Video
Video
₹5585.99
Modern Python Cookbook
Modern Python Cookbook
Read more
Jul 2024818 pages
Full star icon4.9 (21)
eBook
eBook
₹799.99₹3276.99
₹4096.99
Right arrow icon

Customer reviews

Top Reviews
Rating distribution
Full star iconFull star iconFull star iconFull star iconHalf star icon4.9
(21 Ratings)
5 star85.7%
4 star14.3%
3 star0%
2 star0%
1 star0%
Filter icon Filter
Top Reviews

Filter reviews by




N/ANov 05, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Feefo Verified reviewFeefo
Samuel de ZoeteOct 01, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
There are many good books to learn how to code in Python. However, most books and courses show you how it's done and move on to the next topic. This book is different. It not only shows you how it's done, it will explain why it's done this way and how it works. This additional inside is going to make a difference in you being an average programmer or being a really good one!
Amazon Verified reviewAmazon
Stephan MillerAug 03, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
Many coding books lose much of their usefulness after you learn the concepts they have to teach you. But recipe books are great because they become permanent references. When you want to do something specific, you can go right to it. Sometimes I just browse them to see if there is any code that triggers an idea or to run into something I never thought of doing. And this book has more than 130 recipes in my favorite programming language.
Amazon Verified reviewAmazon
RobertAug 04, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
The review covers the third edition of Modern Python Cookbook. This book is not necessarily for the first-time Python user, but if you have some previous experience, this book is the one you want in your collection. It starts with simple Python lessons about numbers, strings, and tuples then progresses into functions, lists, dictionaries, and how to create classes. The chapter about graphics and visualization using the Jupyter notebook was a nice touch. The book is easy to follow and the examples are extremely helpful. I highly recommend this book.
Amazon Verified reviewAmazon
Paul GerberAug 05, 2024
Full star iconFull star iconFull star iconFull star iconFull star icon5
I've recently finished reading "Modern Python Cookbook 3rd Edition" by Steve Lott, and I must say it was an absolutely delightful read. This book is packed with practical recipes and examples that cater to both intermediate and advanced Python developers.One of the standout features of this book is its clear and concise explanations, which made it easy to grasp even the more complex concepts.Another highlight was the section on testing and debugging. The recipes on using pytest and mocking were extremely useful.Steve Lott's emphasis on writing clean and maintainable code resonated with me deeply. His approach to leveraging Python's powerful features like decorators, context managers, and metaclasses has not only improved the quality of my code but also boosted my productivity.Overall, "Modern Python Cookbook 3rd Edition" is a treasure trove of Python wisdom. Whether you're looking to refine your skills or seeking new techniques to tackle challenging problems, this book is an invaluable resource. Highly recommended for anyone serious about mastering Python!
Amazon Verified reviewAmazon
  • Arrow left icon Previous
  • 1
  • 2
  • 3
  • 4
  • 5
  • Arrow right icon Next

About the author

Profile icon Steven F. Lott
Steven F. Lott
LinkedIn iconGithub icon
Steven Lott has been programming since computers were large, expensive, and rare. Working for decades in high tech has given him exposure to a lot of ideas and techniques, some bad, but most are helpful to others. Since the 1990s, Steven has been engaged with Python, crafting an array of indispensable tools and applications. His profound expertise has led him to contribute significantly to Packt Publishing, penning notable titles like "Mastering Object-Oriented," "The Modern Python Cookbook," and "Functional Python Programming." A self-proclaimed technomad, Steven's unconventional lifestyle sees him residing on a boat, often anchored along the vibrant east coast of the US. He tries to live by the words “Don't come home until you have a story.”
Read more
See other products by Steven F. Lott
Getfree access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook?Chevron down iconChevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website?Chevron down iconChevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook?Chevron down iconChevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support?Chevron down iconChevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks?Chevron down iconChevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook?Chevron down iconChevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.


[8]ページ先頭

©2009-2025 Movatter.jp