You need to understand Python well before you can write idiomatic, or pythonic code in it.
But what does that even mean?
Here are some examples
Falsy and Truthy
Almost all data types can be interpreted as bool-ish. An empty list? Fals-y. A 3-character string? Tru-thy
# Instead of writing something like this
a = [1, 2, 3]
if len(a) > 0:
...
# You could write:
a = [1, 2, 3]
if a:
...
Ternary operator
Python does have a ternary operator by leveraging one-line ๐๐s:
# Instead of the lenghty version
a = True
value = 0
if a:
value = 1
# You could shorten it to:
a = True
value = 1 if a else 0
Chained Comparison Operators
Python syntax should be as simple as possible. That's why you can use mathematics-like notations like this
๐ป < ๐ก < ๐ท๐ถ
# Instead of this
if x < 10 and x > 5:
...
# you can write this
if 5 < x < 10:
...
Multiple assignment and destructuring assignment
You can assign different variables in one line of Python code
# Instead of writing
x = 'foo'
y = 'foo'
z = 'foo'
# or
a = [1, 2, 3]
x = a[0]
y = a[1]
z = a[2]
# you could simplify to:
x = y = z = 'foo'
# and
a = [1, 2, 3]
x, y, z = a
f-strings
f-strings provide a template-like mini-language inside Python. You can, for example, align text, or specify precisions of float
s.
username = "Bas"
monthly_price = 9.99
# Instead of transforming each element,
print(username.rjust(10), '|', "{:3.2f}".format(monthly_price))
# you can use a single f-string
print(f"{username : >10} | {monthly_price:3.2f}")
list comprehensions / dict comprehensions
list and dict comprehensions are maybe the most Pythonic feature. It can be very useful for modifying data structures.
usernames = ["alice", "bas", "carol"]
# Instead of a loop:
users_with_a = []
for username in usernames:
if username.startswith("a"):
users_with_a.append(username)
# Use a list comprehension
users_with_a = [username for username in usernames if username.startswith("a")]
# Same for dicts: Instead of a loop
users_dict = {}
for username in usernames:
users_dict[username] = get_user_id(username)
# you can use dict comprehensions
users_dict = {username: get_user_id(username) for username in usernames}
in
keyword
Python has the in
operator that works on collections, like lists.
You could use it to check if an element is in a list of choices
name = 'Alice'
found = False
if name == 'Alice' or name == 'Bas' or name == 'Carol':
...
name = 'Alice'
if city in {'Alice', 'Bas', 'Carol'}:
...
enumerate
Whenever you need to not only access each element by a list but also need a counter in your loop, you can use enumerate
a = ["A", "B", "C"]
# Instead of using an index variable
for i in range(len(a)):
print(i, a[i])
# you could iterate the list as usual and attach a counter
for counter, letter in enumerate(a):
print(counter, letter)
The Walrus Operator
With the walrus operator introduced in Python 3.8, you have an assignment expression.
That means that you could assign a value to a variable and access that value in the same line.
n = len(a)
if n > 10:
print(f"List is too long ({n} elements, expected <= 10)")
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
assert
Assertions inside your code not only make it safer but also help with understanding your rationale behind a particular line.
# Instead of a comment
def activate_user(user):
# User has to be a `UserModel` object
user.active = True
user.save()
# you can use assert
def activate_user(user):
assert type(user, UserModel)
user.active = True
user.save()
Pattern Matching
Pattern Matching is a very handy feature added in Python 3.10.
I had a Twitter thread on this in March:
What are some things you consider as idiomatic Python?
Share your ideas! ๐ก๐
Top comments (8)
Really useful tips :)
Thank you!
Are asserts still removed when python runs with -O? If so what does that mean for code accuracy by using asserts?
assert
s would be removed. Apart from tools likepy2exe
I have barely seen-O
in the wild.But, yes, the
assert
s would render useless โ so it's important to have a good test coverage.Wow I didnโt know half of these existed!
Glad that it helped!
I really like these simple, easy to understand examples ๐
Context managers, generators, operator overloading.