Tips & Tricks Tutorials

Python 3.8 support in PyCharm

The release of Python 3.8 brought new features to the Python coding realm. The language is evolving according to its community’s needs by addressing cases where new syntax or logic become necessary. From new ways of assigning expressions to restriction of usage of function declarations, calls, and variable assignations, this latest release presents new options to code. Of course, PyCharm couldn’t get behind, so we now support some of the major features coming with this new version.

This article will walk you through the features currently supported by our latest PyCharm release. To try them out, get the latest version of PyCharm and download the current beta release of Python 3.8 from here. From there you will just need to switch to Python 3.8 as your interpreter in PyCharm (if you’re not sure how to switch the interpreter, jump into our documentation for help).

Positional-only parameters

Function definitions are a key element when designing libraries and APIs for user consumption. The more explicit these definitions are, the easier they are to implement. One way to achieve such explicitness is by how the function can be called with its arguments. As of now, Python only had the option to define arguments as positional, keyword, or keyword-only, but with this new version we now have another way to define them by using positional-only parameters.

To use this feature, just set the arguments in your function definition and write a forward slash`/` after the last positional-only argument you want to declare. This is closely analogous to the keyword-only arguments syntax, but instead of setting the arguments after the asterisk`*`, you do it before the slash`/`.

Let’s look at an example. Say, you have a function in your library that selects a value randomly from different values passed as arguments. Such values can be passed in any position and the function will return you a random choice. The semantic meaning stays the same, regardless of the order of the values in the function call. By design, you decide that those arguments should be positional-only:

positional-only-random

By doing this, you ensure that your library’s users won’t be able to call your function with the arguments’ keywords. In the past, if you renamed the arguments of your function for refactoring purposes (or any other reason), the code of your library’s users would be at risk if they were to make a function call with keyword arguments (for example, `select_random(a=3, b=89, c=54)`). One of the advantages of positional-only parameters is that, if you decide to change the variable names in the function definition, your library’s users won’t be affected as there are no keyword dependencies in the function calls they make to begin with.

Assignment expressions

A new way to assign values to variables is available with this latest Python version. Now, expressions can also assign values as part of their declaration, which removes the necessity to initialize variables in advance. As a result, you can make your code less verbose and add compactness, as declarations can be made within expressions in the same line.

The syntax to declare a variable consists of the walrus operator `:=` inside an expression enclosed by parentheses. An important note is that the walrus operator is different from the equals operator. For example, comma-separated assignments with the equals operator are not the same as the ones made by the walrus operator.

One example of such usage can be a while loop with a control variable. When you use this feature, the loop’s control expression will also hold the variable definition and reassignment.

assignment-expressions

In the previous example, the ‘before’ while loop has a variable assignment before it and also inside its execution code. The ‘after’ loop has the assignment inside its control statement definition by using an assignment expression.

Final annotation and final decorator

When you design a class, you have to make sure your methods are used properly. With this new version, a final decorator and a `Final` type annotation are introduced to help restrict the usage of methods, classes, and variables. If needed, this feature will let you declare that a method should not be overridden, that a class should not be subclassed, or that a variable or attribute should not be reassigned.

The final decorator prohibits any class decorated with `@final` from being subclassed, and any method decorated with `@final` from being overridden in a subclass. Let’s say you have a class that declares a method and that method is being used inside the class at different points. If the user modifies that method by overriding it while subclassing, there are risks that the base class behavior might change or run into errors. To avoid this, you can use the final decorator to prevent the user from overriding such a class.

Let’s say you have a signature generator class like the following:

final-decorator-attribute

When initialized, the signature is generated through a `create_signature ` method which is called within the `__init__` constructor method. Depending on your class design, you may opt to protect your `create_signature` method with the final decorator so it is not overridden if subclassed. With the final decorator, you ensure that any other method that depends on this method inside the class is not affected by a method override. In this case, the `__init__` constructor method is using the `create_signature` method. By using the final decorator, you ensure that the initialization of the class will not be affected by any change that might be introduced by subclassing.

Another thing to notice is that in this example, we use the `Final` attribute with the `ENCODER` attribute. This class attribute holds the type of string encoding used in the `create_signature` method. By class design, we choose to use the `Final` attribute because we use that value within the methods of the class and we don’t want it to be overridden as that would change the methods’ behavior.

Equals sign in f-strings

String formatting makes code more concise, readable, and less prone to error when exposing values. Variable names and values now can coexist in string contexts with the introduction of the equals sign in f-strings.

To take advantage of this new feature, type your f-string as follows: `f'{expr=}’` where `expr` is the variable that you want to expose. In this way, you get to generate a string that will show both your expression and its output.

f-strings-equals

This feature is helpful when you’d like to write variable values to your log. If you happen to use this for debugging purposes, you may want to check out PyCharm’s debugger.

Learn more

For more information about usages and examples where these features can be useful, take a look at PEP-0570, PEP-0572, PEP-0591, and bpo-36817.

We at PyCharm continue to work on supporting Python 3.8 fully, and we hope these features will come in handy for you when setting up or working with a project using Python 3.8. Support for other features should be expected in the near future, so be sure to pay close attention to our latest releases.

If you have any questions or suggestions, drop us a comment. Thanks!

image description