This post documents the new syntax features I learned about while reading cpython internals.
You can create more than one context manager on a single line.
So for example Shaken Fist contains code like this:
with open(path + '.new', 'w') as o:
with open(path, 'r') as i:
...
That can now be written like this:
with open(path + '.new', 'w') as o, open(path, 'r') as i:
...
You can assign values in a while statement, but only one.
Instead of this:
d = f.read(8000)
while f:
...
d = f.read(8000)
You can write this:
while d := f.read(8000):
...
But unfortunately this doesn’t work:
while a, b := thing():
...
You can use underscores as commands in long numbers to make them easier to read.
For example, you can write 1000000 or 1_000_000 and they both mean the same thing.
You can refer to positional arguments by name, but you can also disable that.
I didn’t realise that this was valid python:
def foo(bar=None):
print(bar)
foo(bar='banana')
You can turn it off with a forward slash in the argument list though, which should separate positional arguments from named arguments:
def foo(bar, /, extra=None):
print(bar)
print(extra)
foo('banana', extra='frog')
The above example will work, whereas this wont:
>>> foo(bar='banana', extra='frog')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() got some positional-only arguments passed as keyword arguments: 'bar'
yield from lets you “delegate” yielding values in an interator
This one is interesting. So if you find yourself writing code like this:
def get_things():
while thing in find_one_category():
yield thing
while thing in find_another_category():
yield thing
Then you can instead write that as:
def get_things():
yield from find_one_category()
yield from find_another_category()
Which is much nicer.