Skip to content

Program in Pythonic way

homepage-banner

Python programming skills that conform to Pythonic habits

One of the biggest advantages of Python is its concise syntax. Good code is clean, tidy and easy to understand, just like pseudocode. To write Pythonic (elegant, authentic, and neat) code, you need to read more and learn from the great code written by experts. There are many excellent source code on GitHub worth reading, such as requests, flask, and tornado. Here are some common Pythonic practices.

0

“Programs must be written for people to read, and only incidentally for machines to execute.”

1. Swap Assignment

##Not Recommended
temp = a
a = b
b = a

##Recommended
a, b = b, a  #  First generate a tuple object, then unpack

2. Unpacking

##Not Recommended
l = ['David', 'Pythonista', '+1-514-555-1234']
first_name = l[0]
last_name = l[1]
phone_number = l[2]

##Recommended
l = ['David', 'Pythonista', '+1-514-555-1234']
first_name, last_name, phone_number = l
# Python 3 Only
first, *middle, last = another_list

3. Use the in operator

##Not Recommended
if fruit == "apple" or fruit == "orange" or fruit == "berry":
    # Multiple judgments

##Recommended
if fruit in ["apple", "orange", "berry"]:
    # Use in for more conciseness

4. String Operations

##Not Recommended
colors = ['red', 'blue', 'green', 'yellow']

result = ''
for s in colors:
    result += s  #  Discard the previous string object each time you assign a value, and generate a new object

##Recommended
colors = ['red', 'blue', 'green', 'yellow']
result = ''.join(colors)  #  No additional memory allocation

5. The List of Dictionary Keys and Values

##Not Recommended
for key in my_dict.keys():
    #  my_dict[key] ...

##Recommended
for key in my_dict:
    #  my_dict[key] ...

# Only if you need to change the key value in the loop, you need to use the my_dict.keys() method to generate a static key value list.

6. Dictionary Key Value Judgment

##Not Recommended
if my_dict.has_key(key):
    # ...do something with d[key]

##Recommended
if key in my_dict:
    # ...do something with d[key]

7. The Dictionary get and setdefault Methods

##Not Recommended
navs = {}
for (portfolio, equity, position) in data:
    if portfolio not in navs:
            navs[portfolio] = 0
    navs[portfolio] += position * prices[equity]
##Recommended
navs = {}
for (portfolio, equity, position) in data:
    # Use the get method
    navs[portfolio] = navs.get(portfolio, 0) + position * prices[equity]
    # Or use the setdefault method
    navs.setdefault(portfolio, 0)
    navs[portfolio] += position * prices[equity]

8. Judgment of Truth

##Not Recommended
if x == True:
    # ....
if len(items) != 0:
    # ...
if items != []:
    # ...

##Recommended
if x:
    # ....
if items:
    # ...

9. Traverse the List and Index

##Not Recommended
items = 'zero one two three'.split()
# Method 1
i = 0
for item in items:
    print i, item
    i += 1
# Method 2
for i in range(len(items)):
    print i, items[i]

##Recommended
items = 'zero one two three'.split()
for i, item in enumerate(items):
    print i, item

10. List Comprehension

##Not Recommended
new_list = []
for item in a_list:
    if condition(item):
        new_list.append(fn(item))

##Recommended
new_list = [fn(item) for item in a_list if condition(item)]

11. Nested List Comprehension

##Not Recommended
for sub_list in nested_list:
    if list_condition(sub_list):
        for item in sub_list:
            if item_condition(item):
                # do something...
##Recommended
gen = (item for sl in nested_list if list_condition(sl) \
            for item in sl if item_condition(item))
for item in gen:
    # do something...

12. Nested Loop

##Not Recommended
for x in x_list:
    for y in y_list:
        for z in z_list:
            # do something for x & y

##Recommended
from itertools import product
for x, y, z in product(x_list, y_list, z_list):
    # do something for x, y, z

13. Use Generators Instead of Lists as Much as Possible

##Not Recommended
def my_range(n):
    i = 0
    result = []
    while i < n:
        result.append(fn(i))
        i += 1
    return result  #  Returns a list

##Recommended
def my_range(n):
    i = 0
    result = []
    while i < n:
        yield fn(i)  #  Uses a generator instead of a list
        i += 1
##Use generators instead of lists as much as possible, unless you must use the list-specific function.

14. Use imap/ifilter for Intermediate Results Instead of map/filter

##Not Recommended
reduce(rf, filter(ff, map(mf, a_list)))

##Recommended
from itertools import ifilter, imap
reduce(rf, ifilter(ff, imap(mf, a_list)))
##Lazy evaluation will bring higher memory usage efficiency, especially when dealing with large data operations.

15. Use the any/all Function

##Not Recommended
found = False
for item in a_list:
    if condition(item):
        found = True
        break
if found:
    # do something if found...

##Recommended
if any(condition(item) for item in a_list):
    # do something if found...

16. Attribute property

##Not Recommended
class Clock(object):
    def __init__(self):
        self.__hour = 1
    def setHour(self, hour):
        if 25 > hour > 0: self.__hour = hour
        else: raise BadHourException
    def getHour(self):
        return self.__hour

##Recommended
class Clock(object):
    def __init__(self):
        self.__hour = 1
    def __setHour(self, hour):
        if 25 > hour > 0: self.__hour = hour
        else: raise BadHourException
    def __getHour(self):
        return self.__hour
    hour = property(__getHour, __setHour)

17. Use with to Handle File Open

##Not Recommended
f = open("some_file.txt")
try:
    data = f.read()
    # Other file operations...
finally:
    f.close()

##Recommended
with open("some_file.txt") as f:
    data = f.read()
    # Other file operations...

18. Use with to Ignore Exceptions (Python 3 Only)

##Not Recommended
try:
    os.remove("somefile.txt")
except OSError:
    pass

##Recommended
from contextlib import ignored  # Python 3 only

with ignored(OSError):
    os.remove("somefile.txt")

19. Use with to Handle Locking

##Not Recommended
import threading
lock = threading.Lock()

lock.acquire()
try:
    # Mutual operation...
finally:
    lock.release()

##Recommended
import threading
lock = threading.Lock()

with lock:
    # Mutual operation...

20. Reference

  1. Idiomatic Python: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
  2. PEP 8: Style Guide for Python Code: http://www.python.org/dev/peps/pep-0008
Leave a message