Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Smaller Changes

00:00 In the previous lesson, I showed you some things that may make development more pleasurable. In this lesson, I’ll show you some of the smaller changes in 3.15.

00:09 A few things have been done to the math module, including the creation of a submodule for functions that deal with integers, and some new functions for dealing with some floating-point special cases like not a number. Let’s get mathy.

00:24 The floating-point specification has some special markers like infinity and not a number, or NaN to its friends. NaN is returned when you do things that are undefined, like dividing zero by zero.

00:37 So, it is a floating-point value, but not a number, which makes its behavior a little unpredictable. Let me show you an example.

00:47 So that means NaN is big, right?

00:53 Or does it? Just what is going on here? Well, one way libraries deal with NaN comparisons is to always return False. So when max() gets run the first time, it checks if nan is smaller than 3.5.

01:07 That’s False. So any further comparison, if there were other numbers, would all result in nan being the max value. But that also means checking if 3.5 is smaller than nan also returns False.

01:19 So in the second case, the comparison returns 3.5 as the bigger thing, giving you a different result. Not all math libraries behave this way. In fact, the C11 compiler standard states that nan should be treated like it isn’t there.

01:34 Rather than break the existing behavior, Python 3.15 introduces a new function.

01:42 The new fmax() function in the math module adheres to the C11 standard, meaning no matter the order,

01:53 fmax() acts like nan isn’t there. So 3.5 is consistently the largest thing. As you might expect, there is an fmin() to go with fmax().

02:07 Another weirdness of the floating-point library is that you have signed zero.

02:14 Yep, it supports both positive and negative values of zero. You could argue that this is an artifact of how floating-point numbers are stored in memory, or some people argue that this allows you to represent things like negative values approaching zero in a limit. Either way, because it’s part of the spec, people have used it.

02:32 Until Python 3.15, there was no easy way to find the sign of a zero value, but now there is. signbit() returns True if the negative sign is present. The name is a reference to the bit in the floating-point representation that when turned on indicates a negative value.

02:54 The call also works for negative infinity. At least that one makes a little more sense. Most of the math library has to do with floating-point numbers.

03:04 There are a few exceptions though. To be a little more organized and make it a little more self-evident, these integer functions have now been moved into a new submodule.

03:20 I probably shouldn’t have said moved. To keep compatibility, the old names are still there as aliases, but I suspect new integer functions going forwards will only be in the submodule.

03:33 Organizing all the changes into a coherent course can be a bit of a challenge. There are only so many synonyms for the word miscellaneous. There is another situation where Python did something a little different from other languages.

03:45 The match() function in the regular expression library anchors matches at the beginning of the text. Most other languages do this differently, where match() is anywhere in the text.

03:56 Closer to Python’s findall() behavior. To make it easier for folks coming from other languages, a new prefixmatch() function has been added.

04:05 The old match() will be soft deprecated. It won’t be removed, but using it is no longer recommended. For clearer code, use prefixmatch() instead.

04:15 Speaking of miscellaneous, another quick one is a new argument to the json library allowing you to change what kind of object array items get put into.

04:25 These things may be small, but they’re worth showing off. Back to the REPL with you. First, the regex mess.

04:35 The findall() method takes an expression, my example here looks for four digits in a row, and returns a list of all the matches. In most other languages, this function would be named match(). In Python, match() only returns the first value found.

04:56 You can see that here in the match object, where the match argument to the match object is the first and only match, 1234.

05:11 To be clearer, this is now called prefixmatch(), indicating that it is only matching things at the start of the text. When you load an array from JSON data, historically it became a list in Python.

05:29 But now, with the array_hook argument,

05:37 you can pass in a class that takes a collection as an argument and an instance of that class will be populated with the values. This can mean more efficient code.

05:47 If you’re not editing the content, tuples can be a better choice than lists. Next up, even more stuff that doesn’t neatly categorize into a single lesson in the course.

Become a Member to join the conversation.