Srikanth Technologies

New Features of Python 3.8

Python 3.8 was released in Oct, 2019 with a couple of new features to language. In this blog, I show you how to use them with relevant code examples.

Walrus Operator

A new operator called Walrus operator was introduced in 3.8. It is used for assigning a value to variable and use the variable in the expression at the same time.

We can assign a value to a variable, but cannot use the value of the variable in the same statement when = is used.

In the following code, we want to find position and space in variable name and display its position. If it is not found then display error message.

name  = "Python Language"
if (pos = name.find(" ")) >= 0:
     print(f"Found space at : {pos}")
else:
    print("Found no space!")

The above code is not valid as we cannot create a variable and use it in the same statement, so we get the following error message:

if (pos = name.find(" ")) >= 0:
            ^
SyntaxError: invalid syntax

However, by using walrus operator (:=), we can assign the value to a variable and also use the variable in the same statement for comparison as shown below. The only change from previous code is replacing normal assignment (=) with walrus operator (:=).

name = "Python Language"
if (pos := name.find(" ")) >= 0:
     print(f"Found space at : {pos}")
else:
    print("Found no space!")

Here is another example where we can use Walrus operator to make code more compact.

names = []
while (name := input("Enter your name [end to stop] : ")) != 'end':
    names.append(name)

print(sorted(names))

Positional-only Parameters

It is already possible to create a function that takes only keyword arguments in Python. Starting from 3.8, we can create a function that takes only positional parameters by giving character / after all positional parameters.

def add(a, b, /):      
    return a + b

print(add(10, 20))

In the above, function add() can take only positional parameters as we gave / at the end. This is similar to giving * before keyword only arguments.

If you try to call add() with keyword arguments as shown below, an error is raised.

print(add(a=20, b=20))

The above code when checked with mypy will throw the following error:

TypeError: add() got some positional-only arguments passed as keyword arguments: 'a, b'

Enhanced f string

It is possible to display name of the variable and value by using = at the end of variable name in f string.

name = "Python"
print(f"{name}")
print(f"{name=}")

The above code will output the following:

Python
name='Python'

Type Hints

Hints have been around in Python for some time. Hints are used to add static type checking in Python language.

To implement static type checking, where we check whether a variable is of required type, we need to use hints feature of the language along with mypy tool after installing it using:

pip install mypy

The following code demonstrates how we can ensure the parameters for function add() are ints and it returns a value of type int.

def add(a: int, b: int) -> int:
    return a + b

print(add(10,20))
print(add("Xyz","Abc"))

In order to check the above code for correct types, we need to use tool mypy as follows:

C:\dev\python>mypy hints_demo.py
hints_demo.py:6: error: Argument 1 to "add" has incompatible type "str"; expected "int"
hints_demo.py:6: error: Argument 2 to "add" has incompatible type "str"; expected "int"
Found 2 errors in 1 file (checked 1 source file)

Enhancements to typing module

Starting from Python 3.8, the following additions are made to typing module so that more static checking can be done in Python.

Final and final

Decorator @final is used to make a class non-inheritable.

Final construct indicates that a variable value cannot be changed.

# File : final_demo.py

from typing import final
from typing import Final

num : Final = 100
num = 10               # Error num cannot be changed

@final
class Person:
    def __init__(self,name,email):
        self.name = name
        self.email = email

class Student(Person):     # Error Person cannot be inherited
    pass

When you test the above code with mypy, it displays the following:

C:\dev\python>mypy final_demo.py
final_demo.py:6: error: Cannot assign to final name "num"
final_demo.py:14: error: Cannot inherit from final class "Person"
Found 2 errors in 1 file (checked 1 source file)

Module typing has a lot of other type hints.

Literal

Literal is used to specify what are valid values for a variable or a function parameter by listing all valid values.

from typing import Literal

def print_message(message : str, case  : Literal['u','l'] = 'u'):
    if case == 'u':
        print(message.upper())
    else:
        print(message.lower())

print_message("Hello")
print_message("Hello","n")

Checking the above code with mypy will detect the following errors:

C:\dev\python>mypy literal_hint.py
literal_hint.py:11: error: Argument 2 to "print_message" has incompatible type "Literal['n']"; expected "Union[Literal['u'], Literal['l']]"
Found 1 error in 1 file (checked 1 source file)

Miscellaneous new features

The following are other new features of Python 3.8.

For a complete list of New Features of Python 3.8, check its official documentation.