DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Structured Logging
  • Integrating AWS With Salesforce Using Terraform
  • Managing Data Residency, the Demo
  • Web Development Checklist

Trending

  • Structured Logging
  • Integrating AWS With Salesforce Using Terraform
  • Managing Data Residency, the Demo
  • Web Development Checklist
  1. DZone
  2. Coding
  3. Languages
  4. Python 3.8 New Features — Code Name Walrus

Python 3.8 New Features — Code Name Walrus

See what's new in your favorite light-weight language!

vasil koicev user avatar by
vasil koicev
·
Updated Dec. 16, 19 · Tutorial
Like (3)
Save
Tweet
Share
14.70K Views

Join the DZone community and get the full member experience.

Join For Free

walrus-sleeping-on-beach

He chonk

A brief and practical guide to the most important/interesting new features/changes coming with Python 3.8 (code name - walrus - joking :) ). So, first let's announce the news:

Python 3.8 was released on October 14th, 2019.

The official documentation is here:

  • What’s New In Python 3.8 - Full documentation.
  • Major new features of the 3.8 series, compared to 3.7 - Short description.

If you want to play with the new features without installing the latest Python 3.8, you can do it here: Python 3.8 (pre-release)

A brief video showing the new features.

You may also like: Core Python.

Overview

In this article, we are going to have a brief, high-level review of some of the new features. Python 3.8 comes with a new Warlus Operator, positional-only parameters, and lots of other new and interesting changes, improvements, and features. It also offers plenty of language changes, one new module, and improvements on others.

Many optimizations and C API changes can be found in the version. Several methods and commands are deprecated.

Personally, I'll not move to python 3.8 soon. Nothing is so important or a game-changer for the moment. Some features could be tricky or cause confusion, which is another reason for me to stick to 3.7 for the moment.

New Features

For me, the most interesting new features are:

  • The Walrus Operator.
  • Positional-only parameters.
  • f-strings support =

The Walrus Operator :=

In short, this is a new operator that will be used as an assignment or named expression. The official description from the PEP describes it as follows:

This is a proposal for creating a way to assign to variables within an expression using the notation NAME := expr.

If you wonder why it's called like this:

It is affectionately known as "the walrus operator" due to its resemblance to the eyes and tusks of a walrus.

The best way to understand the new operator is by viewing some examples like:

Avoid repeated expression calls:

num = 3
if (n := num % 2) != 0:
    print(f"Number is not even: number: {num}, remainder: {n}")


Result:

Number is not even: number: 3, remainder: 1      


Regex expressions

import re, datetime
text = 'The latest version of python 3.8 is released on 14-10-2019 .. '

# before walrus
whole_match = re.findall(r'[\d]{1,2}-[\d]{1,2}-[\d]{4}', text)
if whole_match:
    print(whole_match)

# after walrus
if (found_date := re.findall(r'[\d]{1,2}-[\d]{1,2}-[\d]{4}', text)):
    print(found_date)


List comprehension

If a value computed in a filtering condition is also needed in the expression body:

numbers = [3, '0', 0, '6', 2, 1, 0, '7']
print([final_number for number in numbers if (final_number := int(number)) != 0])


Result:

[3, 6, 2, 1, 7]


Errors and usage:

Sometimes, the walrus operator can be misleading and lead to confusion or errors. So, it might be a good idea to limit its usage to simple cases and expressions in order to avoid problems with code readability.

Below, you can find list comprehension and walrus operator, which leads to an error:

numbers = [3, 0, 0, '6', 2, 1, 0, '7']
[number for number in numbers if (number := int(number)) != 0]

SyntaxError: assignment expression cannot rebind comprehension iteration variable 'number'


Another interesting case and possible abuse is:

if (I := he ) or ( you := me ) and ( we := alltogether):
    I = walrus


You can read more here: I walrus

The full description is available here: PEP 572

Positional-Only Parameters

A new syntax for function parameters is introduced —  /. This is an example function:

def f(a, /, b, *, c):
    print(a, b, c)


In this function parameter a  is a positional-only and cannot be a keyword argument. While on the other hand c must be a keyword argument.

Let's check several examples:

Correct call for this function:

f(10, 20, c=30)


Result:

10 20 30

TypeError: f() takes 2 positional arguments but 3 were given

f(10, 20, 30) # c must be a keyword argument


Results in:

TypeError: f() takes 2 positional arguments but 3 were given

TypeError: f() got some positional-only arguments passed as keyword arguments: 'a'

f(a=10, b=20, c=30)   # a cannot be a keyword argument


Results in:

TypeError: f() got some positional-only arguments passed as keyword arguments: 'a'

Positional-only parameters can be used in two ways. Their names are not shown as possible keywords, which makes them available for kwargs:

def f(x, /, **kwargs):
    print(x, kwargs)

f(10, x=1, y=2)         # x is used in two ways
10 {'x': 1, 'y': 2}


For more info: Python Positional-Only Parameters.

F-Strings Support for Self-Documenting Expressions and Debugging

In 3.8 there is added support for = for f-strings. So f-string like:

 f'{version=} is released on {release_date=}' 

will be represented as:

 

version='3.8' is released on release_date=datetime.date(2019, 10, 14)

 


Few more examples on this

from datetime import date

version = '3.8'
release_date = date(2019, 10, 14)
python_one_version = date(1994, 1, 1)

since_python_one = release_date - python_one_version

print(f'{version=} is released on {release_date=}')
print(f'{version=} day of Release {python_one_version.day=:02d}')
print(f'{version=} day of Release {since_python_one.days=:,d}')


Results:

version='3.8' is released on release_date=datetime.date(2019, 10, 14)
version='3.8' day of Release python_one_version.day=01
version='3.8' day of Release since_python_one.days=9,


Used in previous Python versions, like Python 3.7, this will result in:

  File "<fstring>", line 1
    (version=)
            ^
SyntaxError: invalid syntax


The main idea is:

#(really) bad old days this was pretty wordy:
print "foo=", foo, "bar=", bar

#f-strings make this slightly nicer to type:
print(f"{foo=} {bar=}")


Result:

foo=datetime.date(2019, 10, 14) bar=1


Other New Features

Some of the features cannot be easily explained with examples so I'll just list them:

  • Parallel filesystem cache for compiled bytecode files.
  • Debug build uses the same ABI as release build.
  • PEP 578: Python Runtime Audit Hooks.
  • PEP 587: Python Initialization Configuration.
  • Vectorcall: a fast calling protocol for CPython.
  • Pickle protocol 5 with out-of-band data buffers.

Other Language Changes

In this section, there are some quite interesting changes which might need your attention when you migrated from older Python version to 3.8 like:

  • The continue statement is now allowed in the  finally clause.
  • The new method as_integer_ratio() for bool,  int, and Fraction types:
x = 7
print(x.as_integer_ratio())


Result:

(7, 1)


  • Added support of \N{name} escapes in regular expressions:
import re

notice = 'Copyright © 2019'
copyright_year_pattern = re.compile(r'\N{copyright sign}')
print(copyright_year_pattern.search(notice).group(0))


This will error in earlier versions:

sre_constants.error: bad escape \N at position 0

  •  Dict and dictviews are now iterable in reversed insertion order using reversed(). 
  • Warnings when a comma is missing in code like: [(1, 2) (3, 4)]. 

Before:

  File ".code.tio", line 1, in <module>
    [(1, 2) (3, 4)]
TypeError: 'tuple' object is not callable


Now:

SyntaxWarning: 'tuple' object is not callable; perhaps you missed a comma?
  [(1, 2) (3, 4)]
Traceback (most recent call last):
  File ".code.tio", line 1, in <module>
    [(1, 2) (3, 4)]
TypeError: 'tuple' object is not callable


  • Arithmetic operations between subclasses of datetime.date or datetime.datetime and datetime.timedelta objects now return an instance of the subclass, rather than the base class.

For example:

from datetime import datetime, timezone

class DateTimeSubclass(datetime):
    pass

dt = DateTimeSubclass(2012, 1, 1)
dt2 = dt.astimezone(timezone.utc)

print(type(dt))
print(type(dt2))


In Python 3.8

<class '__main__.DateTimeSubclass'>
<class '__main__.DateTimeSubclass'>


Before:

<class '__main__.DateTimeSubclass'>
<class 'datetime.datetime'>


  • When the Python interpreter is interrupted by Ctrl-C (SIGINT), and the resulting KeyboardInterrupt exception is not caught, the Python process now exits via a SIGINT   signal
  •  Dict comprehensions have been synced-up with dict literals, so that the key is computed first and the value second:
from unicodedata import normalize
names = ['Löwis', 'Łukasz', 'Dörwald']
print({(n := normalize('NFC', name)).casefold() : n for name in names})


Result:

{'löwis': 'Löwis', 'łukasz': 'Łukasz', 'dörwald': 'Dörwald'}


Conclusion

Python 3.8 comes with a new assignment operator, syntax for function parameters, and many other improvements and features. At first sight, some of the changes look a bit controversial, but they can offer new solutions to old problems.

The examples covered in the article shows potential for expanding the usage beyond the scope described in PEPs.

Once this version is well adopted, I'll move to it in order to explore the full potential of it.


Further Reading

  • Anaconda Python Tutorial: Everything You Need to Know.
  • Yet Another Android Snake With Kivy, Python.
  • Practical Data Mining with Python.
Python (language) Operator (extension)

Opinions expressed by DZone contributors are their own.

Trending

  • Structured Logging
  • Integrating AWS With Salesforce Using Terraform
  • Managing Data Residency, the Demo
  • Web Development Checklist

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: