Formatted string literals are prefixed with 'f' and are similar to the format strings accepted by str.format(). They contain replacement fields surrounded by curly braces. The replacement fields are expressions, which are evaluated at run time, and then formatted using the format() protocol:
d = 12.768217131912
i = 31
print(f"File {i:06}.txt contains the value {d:.2f}")
File 000031.txt contains the value 12.77
See https://realpython.com/python-f-strings/ for more details.
Type hinting is a formal solution to statically indicate the type of a value within your Python code.
# greetings.py
def greet(name: str) -> str:
return(f"Hello, {name}")
greet("Mira")
'Hello, Mira'
type hints are not checked during runtime
greet(6)
'Hello, 6'
Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or “duck”) typing and static typing.
https://realpython.com/lessons/type-checking-mypy/
# greetings.py
def greet(name: str) -> str:
return(f"Hello, {name}")
greet("Mira")
greet(6)
!mypy greetings.py
greetings.py:6: error: Argument 1 to "greet" has incompatible type "int"; expected "str" Found 1 error in 1 file (checked 1 source file)
from typing import Union
def print_key(key: Union[int, str]):
print(f"key={key}")
from typing import Optional
def foo(arg: Optional[int] = None) -> None:
return None
Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# typechecks; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
adds the ability to use underscores in numeric literals for improved readability.
1_000_000_000_000_000
1000000000000000
0x_FF_FF_FF_FF
4294967295
The string formatting language also now has support for the '_' option to signal the use of an underscore for a thousands separator for floating point presentation types and for integer presentation type 'd'. For integer presentation types 'b', 'o', 'x', and 'X', underscores will be inserted every 4 digits:
'{:_}'.format(1000000)
'1_000_000'
'{:_x}'.format(0xFFFFFFFF)
'ffff_ffff'
pathlib
¶from pathlib import Path
pth = Path("~/projects/ZDO/python_news/")
pth
WindowsPath('~/projects/ZDO/python_news')
pth = pth.expanduser()
pth
WindowsPath('C:/Users/Jirik/projects/ZDO/python_news')
pth.exists()
True
pth.parent
WindowsPath('C:/Users/Jirik/projects/ZDO')
list(pth.glob('*'))
[WindowsPath('C:/Users/Jirik/projects/ZDO/python_news/.ipynb_checkpoints'), WindowsPath('C:/Users/Jirik/projects/ZDO/python_news/.mypy_cache'), WindowsPath('C:/Users/Jirik/projects/ZDO/python_news/greetings.py'), WindowsPath('C:/Users/Jirik/projects/ZDO/python_news/python_36_310.ipynb')]
fn = pth / "greetings.py"
fn
WindowsPath('C:/Users/Jirik/projects/ZDO/python_news/greetings.py')
fn.stem
'greetings'
fn.suffix
'.py'
pth.relative_to(Path.home())
WindowsPath('projects/ZDO/python_news')
The dict type now uses a “compact” representation based on a proposal by Raymond Hettinger which was first implemented by PyPy. The memory usage of the new dict() is between 20% and 25% smaller compared to Python 3.5.
dct = {1:1}
dct[3] = 3
dct[2] = 2
dct
{1: 1, 3: 3, 2: 2}
breakpoint()
function (PEP 553)¶Python 3.7 includes the new built-in breakpoint() function as an easy and consistent way to enter the Python debugger.
print("a")
breakpoint()
print("b")
a --Return-- None > <ipython-input-88-7a90b6c6600b>(2)<module>() 1 print("a") ----> 2 breakpoint() 3 print("b") ipdb> c b
There is new syntax :=
that assigns values to variables as part of a larger expression. It is affectionately known as “the walrus operator” due to its resemblance to the eyes and tusks of a walrus.
In this example, the assignment expression helps avoid calling len() twice:
if (n := len(dct)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
There is a new function parameter syntax /
to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments.
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
Symbol *
indicates Keyword-Only Arguments.
f(10, 20, 30, d=40, e=50, f=60)
10 20 30 40 50 60
Invalid calls
f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
Added an = specifier to f-strings. An f-string such as f'{expr=}' will expand to the text of the expression, an equal sign, then the representation of the evaluated expression.
from datetime import date
user = 'eric_idle'
member_since = date(1975, 7, 31)
f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
delta = date.today() - member_since
f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,604'
s = 'Hello World from Python 3.9!'
print(s.removeprefix('Hello World')) # from Python 3.9!
print(s.removeprefix('')) # Hello World from Python 3.9!
print(s.removesuffix('3.9!')) # Hello World from Python
print(s.removesuffix('Python')) # Hello World from Python 3.9!
from Python 3.9! Hello World from Python 3.9! Hello World from Python Hello World from Python 3.9!
def square(number: Union[int, float]) -> Union[int, float]:
return number ** 2
def square(number: int | float) -> int | float:
return number ** 2