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

Dealing With Numbers

00:00 In the previous lesson, I showed you some new syntax features of Python. This lesson covers several small changes to numbers in Python. There are three small changes to numbers in Python 3.14 that I’m going to cover together.

00:13 First off, is an interesting little corner case dealing with a specific situation with complex numbers. As a bit of background, floats support two values that aren’t actually numbers.

00:24 The first is NaN, meaning ‘not a number’. It gets used when you do weird things like dividing zero by zero. The second value is infinity, which float also supports.

00:34 A complex number consists of two parts, the real part and the badly named imaginary part. Complex numbers often get used in places where you need a vector of size two. Python supports complex numbers, and when you create one, you pass it two values: one for its real part and one for its imaginary part.

00:53 Both of these can be floats, and since float support NaN and infinity, complex numbers can do the same. Unfortunately, the Python implementation of this isn’t quite consistent with the C language standard, making things difficult for anyone writing extension libraries that deal with complex numbers.

01:11 Python 3.14 has changed the behavior to be consistent with the C99 specification. The next change is easier to explain. Both float and complex now have from_number methods on them that convert a given number into float or complex, respectively.

01:28 And the last change I’ll highlight has to do with using underscore as a thousands separator in the decimal part of a float. Let’s go get numeric. Once more, I’ve got Python 3.13 in the top window. Here, I’ve defined a complex number, passing in a real and imaginary value. Python prints this out with its two component parts.

01:53 Mathematicians tend to use i for imaginary, while engineers tend to use j. There was actually a big thread years ago arguing to move this to i, but Guido put his foot down back when he was Benevolent Dictator for Life.

02:07 If you’re curious why engineers use j, I’ve seen a couple of explanations. One is i is current in electrical engineering, so you know that would be confusing.

02:17 And two, it’s common to use i, j, and k for vectors corresponding to the x, y, and z axis. If you do, then the i part of a complex number isn’t the i part of the vector, which is also confusing.

02:31 I’m sure you didn’t need to know any of that. It’s j for jimaginary. Let’s create a complex number using some of those non-number floats.

02:46 An infinite real part with a NaN imaginary component. If you’ve done any math with infinities, you’d know that multiplying them should also return an infinity,

03:03 unless of course you’re Python. The implementation of complex leaks the NaN into the real part. This is what has been fixed in Python 3.14. Let me quickly just do that again,

03:20 and not only is it easier to read with the color formatting, but it also gives a value consistent with the C99 language spec.

03:28 The second numeric feature is the addition of the from_number methods on float and complex.

03:36 You can use the float constructor to change a value into a float, and likewise for complex, but now you can also do that with from_number.

03:53 Why would you want to do this? Well, it makes certain kinds of code easier. Seeing as both floats and complex have the method, it means you can use duck typing and not care which kind of class you’re dealing with.

04:05 If you’re passing a class around, you can just call the method without knowing whether it’s a float or a complex. It’s not a big thing, but for the people working with this, it saves a few lines of code.

04:17 Say you have a large number. Just how many zeroes is that? In the real world, you’d put a comma or a decimal, depending on where you live, to separate out the thousands.

04:29 Python allows you to do this with an underscore. I like this feature. It makes large numbers in your code easier to read. Do note, though, that including it in the number doesn’t include it in the evaluation.

04:42 The REPL still prints out the same thing in both cases, but if you are printing something to the screen, you can take advantage of this idea with a format specifier in an f-string.

04:55 I need a new number to demonstrate this.

04:58 There’s the regular f-string without a format specifier,

05:03 and there’s the underscore format specifier putting an underscore as a thousands separator in the result. And now for the new 3.14 thing.

05:13 Now you can also put a separator in the part to the right of the decimal.

05:20 F-strings also support the use of comma separators as well. Unfortunately, you can’t use periods as thousands separators this way as ... means something else in Python.

05:32 In the next lesson, I’ll cover the new placeholder concept in the functools module.

Become a Member to join the conversation.