It has been interesting couple of moths in Python community. Beta version of Python 3.8 was around since summer and everyone was waiting when the official version is going to be released. At various PyCon conferences people shared their excitement about new changes. The wait finished couple of days ago, on October the 14. Python 3.8 is released and the community can finally have benefits from it.
There are many new features in this release and you can see them all at the official release publication. In a nutshell, there are few big features and a lot of small ones. Apart form that, addition optimization is done, so Python 3.8 should be faster than previous versions. In this article, we will focus on the five features that in our opinion are the most important, the most fun and that they will be used the most.
Assignment Expressions & Walrus Operator
One of the first programming languages that I’ve learned was actually Pascall. I know I am a billion years old, but that is not the point 🙂 In this programming language, variable assignment is done using so-called walrus operator – :=. It is called like that due to the fact that it looks like eyes and tusks of the walrus. Now, this operator is available in Python as well. However, in Python this operator is used for assignment expressions.
Effectively, this means that you can assign and return a value in one statement. Also, this means that you can create variables inside of expressions. For example, you can do something like this:
and get the output:
As you can see the assignment expression (walrus operator) allows you to assign value 11 to the variable x and print it at the same time. This has many benefits and can make code more readable. Especially, if we work with loops and if statements. For example, if you want to avoid calling len parameter twice:
Or, if you want to handle user input in an easier manner, instead of writing something like this:
Now we can utilize walrus operator and write it with fewer lines of code:
This is another syntax feature that will change the way we write our code. What are Positional-Only Parameters? Well, their name say a lot. Basically, value of these function parameters during the function call must be located in the place where they are defined and cannot be used as keyword arguments. By this we mean that if you define function like this:
You can call it like this:
However, you can’t call it like this:
Note that / character is used to define these parameters. Parameters that came before it are positional arguments. So far, this was only available in built in functions like float(). Another cool thing about positional-only parameters is that you can also have them with default values:
Now, if we want to use these with keyword arguments, it can be done like this:
Or you can forbid using keyword arguments at all using /:
This feature is truly awesome. The problem it is trying to solve is two-folded. First problem is that on one end, type hits don’t cover nested dictionaries. Type hints were initially introduced in Python 3.5, however they have problems with nested types. Representing an object or structured data using (often nested) dictionaries with string keys is a common pattern. Python 3.8 allows type hints to perform static type checks without actually running your code on nested dictionaries. Something like this:
This canonical representation of Song will cause no errors when we run some type checker (for example – mypy) is used. This is due to the fact that the dictionary is correct implementation of the Song type. However if we try to do something like this:
We will get errors:
typedicterror.py:11: [1m[31merror:[m Incompatible types (expression has type [m[1m"str"[m, TypedDict item [m[1m"year"[m has type [m[1m"int"[m)[m typedicterror.py:11: [1m[31merror:[m Incompatible types (expression has type [m[1m"int"[m, TypedDict item [m[1m"artist"[m has type [m[1m"str"[m)[m
Literal & Final
At the moment, as a part of Python API there are many functions that return different types depending on the value of some function parameter provided. This is evident in other 3rd party libraries as well. For example, pandas.concat(…) returns either Series or DataFrame depending the axis argument (0 – Series, 1 – DataFrame). Thus far it was impossible to detect type signatures of these functions. Let’s say that you need to implement function that has a parameter whose value should be in some range. For example, if the value of an integer parameter is less than 111, we don’t need to process it:
Laterals are another type check feature that can help us with this:
If we run mypy we will get something like this:
latelars.py:8: [1m[31merror:[m Argument 1 to [m[1m"nBackAtYa"[m has incompatible type [m[1m"Literal"[m; expected [m[1m"Union[Literal, Literal, Literal]"[m[m [1m[31mFound 1 error in 1 file (checked 1 source file)[m
Final objects are another improvement when it comes to type hints and type checks. Basically sometimes we want to prevent classes from being overriden or inherited. Now, we can use
@final decorator. This way we prevent class from being inherited. Apart form that the
Final type is also available and it prevents overrides.
Have you noticed that a lot of Python libraries are only being supported from Python version 3.6 onward. Some people think this is solely to the fact that f-strings were introduced in that version. With these strings you can do something like this:
And the output will be:
' Rubik's Code is awesome!'
Apart from that, you can use variables and expressions inside of f-strings’ curly braces. They are resolved during run-time. The cool thing in Python 3.8 is that you can use them for debugging. How so? Well you can do something like this:
And the output will be:
In this article we had a chance to see just some of the interesting new features that are available in Python 3.8. To see the full list and get detailed information about each of the features, makes sure you check this link or simply go through Python Developers Guide. If you are just starting your Python journey, subscribe to our newsletter and get our Python Basics Guide for free.
Read more posts from the author at Rubik’s Code.