Python, for all its ease of learning, has some pockets of real complexity. If you’ve ever read through the programming language’s documentation, you’ve probably gotten a sense of that. If you’re new to the language, here are some features you might not be familiar with, but could nonetheless prove useful (or at least fun to experiment with).
Negative Strides on Slices
Slices are a fairly modern innovation in several computer languages. In Python, we can use them on lists, tuples and strings to get a subset of a particular sequence. You might be familiar with slices in that context… but did you know you can also use them to reverse a sequence? What do you think this code outputs:
alphabet = [chr(c) for c in range(ord('a'), ord('z')+1)] # 'a'..'z'
print(alphabet[::-5])
That first line puts the entire alphabet into the alphabet variable. The -5
, the third parameter of the slice, is stride, an interval. Because it's negative, it runs backwards.
['z', 'u', 'p', 'k', 'f', 'a']
An Alternative Way to Do Multiple Assignments
You may be familiar with multiple assignments where you assign values to several variables in one statement, like this:
a = b =9
print(f'a={a} b= {b}')
But you can also do multiple assignments this way:
a,b = 5,4
print(f'a={a} b={b}')
This outputs: a=5 b = 4
.
Using the Walrus Operator
This was only recently introduced in Python 3.8. In C, it's not uncommon to assign a value to a variable in ab (an expression). Now, Python has it with the :=
operator.
(This one I had to test using a repl online, as none of the Python versions I had installed on Windows or Ubuntu were version 3.8.)
a= 9
b =-3.4
print(c := a*a+b)
print(c)
The output was 77.6 twice, with C being assigned the value 77.6 in the first print statement.
'Else' Blocks On 'For' and 'While'
This is something that doesn't happen with other programming languages. I personally find using them confusing and have never used them, but if you want to impress your friends or colleagues....
After a for
or while
loop you can have an else
. The else
branch only runs if there was no break in the loop
body.
Here's an example. What do you think it will print out?
for i in range(5):
print(f'loop index={i}')
else:
print(f'else i={i}')
This is the output:
loop index=0
loop index=1
loop index=2
loop index=3
loop index=4
else i=4
It’s pretty confusing! If we try it this way, code below the else
never runs, but it’s just as easy to not use else
.
for i in range(5):
print(f'loop index={i}')
if i==4:
break;
else:
print(f'else i={i}')
My suggestion: Don't use it, just be aware of it so you won’t end up scratching your head if you see it used.
Else
is useful, though, in a try/except
, when comes after the except
and lets you handle code if the specified exceptions don't occur.
In this somewhat contrived example with two user-defined exceptions, the guess function returns exceptions if the value is too small or too large. Only if the value is correct does the else
get hit:
class Error(Exception):
"""Base class for other exceptions"""
pass
class ValueTooSmallError(Error):
"""Raised when the input value is too small"""
pass
class ValueTooLargeError(Error):
"""Raised when the input value is too large"""
pass
def guess(value):
if value <5:
raise ValueTooSmallError
elif value >15:
raise ValueTooLargeError
return value
try:
answer=guess(5)
except ValueTooSmallError:
print("Too small")
except ValueTooLargeError:
print("Too large")
else:
print("Good guess")
Position 'Only' Parameters in Functions
This is another 3.8 feature. When you call a function, you can specify parameters by position or with the name of the parameter. If the parameter list includes a parameter /
and *
, then whether a parameter is positional only, positional or keyword, or keyword only depends upon where the parameter is relative to /
and *
. Note both /
and *
are optional and *
was already used in Python 3.7.
This diagram is taken from PEP 5470:
def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
----------- ---------- ----------
| | |
| Positional or keyword |
| - Keyword only
-- Positional only
The various cases are defined in more detailed in the 3.8 documentation on defining functions.
Conclusion
Staying on top of the changes in a language like Python is never easy, but it can be fun finding out new things! Careful reading of the What’s new in Python 3.xx webpages is a good start; they are already there for both 3.9 and 3.10.