You are on page 1of 10

Python 3.7, 3.8 and 3.

9
new features
New features highlights:
1. Breakpoint (v3.7)
2. Annotations. (All the versions improvements)
3. Final decorator. (v3.8)
4. Walrus Operator. (v3.8)
5. Positional-Only Arguments.(v3.8)
6. Enhancements is f-string. (v3.8)
7. Many improvements in standard modules math, statistics. (v3.8)
8. Warnings About Dangerous Syntax. (v3.8)
9. Proper Time Zone Support (v3.9)
10. Union Operator for dictionaries. (v3.9)
11. String Prefix and Suffix. (v3.9)
Python v3.7
• The breakpoint() Built-In its very handy to debug now

in 3.6 and below

def divide(e, f):


import pdb; pdb.set_trace()
return f / e
divide(0, 1)

in 3.7
def divide(e, f):
breakpoint()
return f / e
divide(0, 1)
• Typing Enhancements
Type hints and annotations have been in constant development throughout the Python 3 series of releases. Python’s typing system is now quite stable.
Still, Python 3.7 brings some enhancements to the table: better performance, core support, and forward references.

class Tree:
def __init__(self, left: Tree, right: Tree) -> None:
self.left = left
self.right = right

Running the code raises a NameError because the class Tree is not yet (completely) defined in the definition of the .__init__() method:
Traceback (most recent call last):
File "tree.py", line 1, in <module>
class Tree:
File "tree.py", line 2, in Tree
def __init__(self, left: Tree, right: Tree) -> None:
NameError: name 'Tree' is not defined
To overcome this, you would have needed to write "Tree" as a string literal instead:
class Tree:
def __init__(self, left: "Tree", right: "Tree") -> None:
self.left = left
self.right = right

from __future__ import annotations


class Tree:
def __init__(self, left: Tree, right: Tree) -> None:
self.left = left
self.right = right
left = list()

Note : In a future Python 4.0, such so called forward references will be allowed
Python v3.8
• The Walrus in the Room: Assignment Expressions

The biggest change in Python 3.8 is the introduction of assignment expressions.
They are written using a new notation (:=).
This operator is often called the walrus operator as it resembles the eyes and tusks of a
walrus on its side.
>>> walrus = False
>>> print(walrus)
False

In Python 3.8, you’re allowed to combine these two statements into one, using the walrus operator:
>>> print(walrus := True)
True
• inputs = list()
while True:
current = input("Write something: ")
if current == "quit":
break
inputs.append(current)
• Can also be written 1 line below instead of 4 lines in above sample
• inputs = list()
while (current := input("Write something: ")) != "quit":
inputs.append(current)

print(walrus := True)
Positional-Only Arguments:
• In Python 3.8, you can use / to denote that all arguments before it must be specified by
position.
In any version of Python 3, you can specify keyword-only arguments using the star (*).
Any argument after * must be specified using a keyword:
• 1 . def incr(x, /):
... return sum(x)
...
>>> incr(3.8)
4.8

>>> incr(x=3.8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: incr() got some positional-only arguments passed as
keyword arguments: 'x’
• 2. def greet(name, /, greeting="Hello"):
return f"{greeting}, {name}"
Final decorator
The final decorator: https://peps.python.org/pep-0591/
The typing.final decorator is used to restrict the use of inheritance and overriding.

A type checker should prohibit any class decorated with @final from being subclassed and any method decorated
with @final from being overridden in a subclass. The method decorator version may be used with all of instance methods,
class methods, static methods, and properties.

For example:

from typing import final


@final
class Base:
...
class Derived(Base): # Error: Cannot inherit from final class "Base"
...
and:
from typing import final

class Base:
@final
def foo(self) -> None:
...
class Derived(Base):
def foo(self) -> None: # Error: Cannot override final attribute "foo"
# (previously declared in base class "Base")
f-strings enhancements
In Python 3.8, you can use assignment expressions inside f-strings. Just make sure to surround the assignment
expression with parentheses:
>>> import math
>>> r = 3.8

>>> f"Diameter {(diam := 2 * r)} gives circumference {math.pi * diam:.2f}"


'Diameter 7.6 gives circumference 23.88'
------------------------------------------------------
Python 3.8 is the new debugging specifier.
>>> python = 3.8
>>> f"{python=}"
'python=3.8'

>>> python = 3.7


>>> f"python={python}"
'python=3.7'

name = "Eric"
>>> f"{name.upper()[::-1] = }"
"name.upper()[::-1] = 'CIRE'"
Other enhancements in v3.8
# Many improvements in standard modules math, statistics
# math.prod((2, 8, 7, 7))
# ------------------------------------------
""“

Warnings About Dangerous Syntax

>>> # Python 3.7


>>> version = "3.7"
>>> version is "3.7"
False

>>> # Python 3.8


>>> version = "3.8"
>>> version is "3.8"
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False

>>> version == "3.8"


True

Many optimizations in memory and code running


Python v3.9
• 1. Proper Time Zone Support
• 2. Union Operator
• >>> pycon = {2016: "Portland", 2018: "Cleveland"}
>>> europython = {2017: "Rimini", 2018: "Edinburgh", 2019: "Basel"}

>>> pycon | europython


{2016: 'Portland', 2018: 'Edinburgh', 2017: 'Rimini', 2019: 'Basel'}

>>> pycon |= europython


>>> pycon
{2016: 'Portland', 2018: 'Edinburgh', 2017: 'Rimini', 2019: 'Basel’}
• >>> libraries = {
... "collections": "Container datatypes",
... "math": "Mathematical functions",
... }
>>> libraries |= {"zoneinfo": "IANA time zone support"}
>>> libraries
{'collections': 'Container datatypes', 'math': 'Mathematical functions',
'zoneinfo': 'IANA time zone support'}

>>> libraries |= [("graphlib", "Functionality for graph-like structures")]


>>> libraries
{'collections': 'Container datatypes', 'math': 'Mathematical functions',
'zoneinfo': 'IANA time zone support',
'graphlib': 'Functionality for graph-like structures'}2
String Prefix and Suffix
>>> "three cool features in Python".strip(" Python")
'ree cool features i'

The suffix " Python" has been removed, but so has "th" at the beginning of the string.
The actual behavior of .strip() is sometimes surprising—and has triggered many bug reports.
It’s natural to assume that .strip(" Python") will remove the substring " Python",
but it removes the individual characters " ", "P", "y", "t", "h", "o", and "n" instead.

In Python 3.9, there are two new string methods that solve this exact use case. You can use
.removeprefix() and .removesuffix() to remove the beginning or end of a string, respectively:

>>> "three cool features in Python".removesuffix(" Python")


'three cool features in'

>>> "three cool features in Python".removeprefix("three ")


'cool features in Python'

>>> "three cool features in Python".removeprefix("Something else")


'three cool features in Python'

You might also like