Improving Python Code: Learning “Pythonic” Writing from Anti-Patterns

Python has a “recommended way of writing” called “Pythonic,” which leverages features and conventions unique to Python. Bringing habits from other programming languages or continuing to write verbose code is called an “Anti-pattern,” which causes poor readability and maintainability.

This article introduces common anti-patterns and compares them with improved code examples to help you write more efficient Python.


目次

1. Use Chained Comparison Operators

When determining if a number falls within a specific range, there is no need to connect expressions using and.

Anti-pattern:

age = 25
# Common in other languages, but verbose in Python
if 18 <= age and age < 60:
    print("Working age")

Improved: You can chain comparison operators just like in mathematical inequalities.

age = 25
# Intuitive and readable
if 18 <= age < 60:
    print("Working age")

2. Use in for Checking Against Multiple Values

When checking if a variable matches any of several candidates, chaining with or is inefficient.

Anti-pattern:

role = "editor"
if role == "admin" or role == "editor" or role == "moderator":
    print("Access granted to admin panel")

Improved: You can summarize conditions concisely using a tuple or set with the in operator.

role = "editor"
# Group candidates in a tuple
if role in ("admin", "editor", "moderator"):
    print("Access granted to admin panel")

3. Truth Value Testing

When checking boolean values or whether a list is empty/non-empty, you do not need to write == True or len() > 0.

Anti-pattern:

is_valid = True
user_list = ["user1"]

if is_valid == True:
    print("Valid")

if len(user_list) > 0:
    print("User exists")

Improved: In Python, if you write a variable directly in a conditional expression, it is automatically evaluated as a truth value (recommended by PEP 8).

  • True: True, non-zero numbers, non-empty containers
  • False: False, None, 0, empty containers ([], "", {})
is_valid = True
user_list = ["user1"]

if is_valid:
    print("Valid")

if user_list:
    print("User exists")

4. Utilizing Ternary Operators (Conditional Expressions)

When assigning a value to a variable based on a simple condition, expanding it into an if-else block makes the code vertically long.

Anti-pattern:

score = 85
result = ""
if score >= 80:
    result = "Pass"
else:
    result = "Fail"

Improved: By using a conditional expression (ternary operator), you can write it in one line.

score = 85
result = "Pass" if score >= 80 else "Fail"

5. No Counter Variable Needed for Sequence Loops

Generating an index (counter) using len() and range() to access list elements is not recommended in Python.

Anti-pattern:

fruits = ["Apple", "Banana", "Cherry"]
# C-style access using index
for i in range(len(fruits)):
    print(fruits[i])

Improved: Passing the list directly to the for statement extracts elements in order from the beginning.

fruits = ["Apple", "Banana", "Cherry"]
# Extract elements directly
for fruit in fruits:
    print(fruit)

6. Assign Simultaneously if Values are the Same

When initializing multiple variables with the same initial value, there is no need to split lines.

Anti-pattern:

x = 0
y = 0
z = 0

Improved: You can initialize at once by chaining =.

x = y = z = 0

7. Utilizing List Comprehensions

When creating a new list from an existing list, creating an empty list and repeating append is verbose and slightly slower.

Anti-pattern:

numbers = [1, 2, 3, 4, 5]
squared_numbers = []
for n in numbers:
    squared_numbers.append(n ** 2)

Improved: Using list comprehension allows for concise and fast writing.

numbers = [1, 2, 3, 4, 5]
squared_numbers = [n ** 2 for n in numbers]

8. Beware of Overwriting Global Names (Shadowing)

If you use built-in function names like list, str, sum, or id as variable names, the original functionality becomes unavailable (Shadowing).

Anti-pattern:

# Should avoid the variable name 'list'
list = [10, 20, 30]

# The original list() function becomes unusable and causes an error
# new_list = list((1, 2)) 
# TypeError: 'list' object is not callable

Improved: Use meaningful variable names or names that do not conflict with type names.

number_list = [10, 20, 30]
# Original function remains available
new_list = list((1, 2)) 

9. No Temporary Variable Needed for Swapping

You do not need to prepare a temporary variable (temp) to swap values between variables.

Anti-pattern:

a = 100
b = 200

temp = a
a = b
b = temp

Improved: Using Python’s tuple unpacking allows for a smart swap in one line.

a = 100
b = 200

a, b = b, a

Summary

Adopting these writing styles not only shortens the code but also clarifies intent and reduces bugs.

  • Chain comparisons.
  • Group multiple candidates with in.
  • Keep truth value testing simple.
  • Loop directly over iterables.
  • Use comprehensions and unpacking.
  • Do not use built-in function names as variable names.

Keep these in mind and aim for Pythonic code.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次