This page is designed to give you a list of concrete examples demonstrating idiomatic (Pythonic) code.
Many of the examples were taken from the following resources:
- PEP 8 - Style Guide for Python Code
- Khan Academy Style Guide
- Hitchikers Guide to Python
- Writing Idiomatic Python
- Python Best Practice Patterns
- Python-tips-tricks-and-idioms
- Little book of Python anti-paterns
Python philosophically distinguishes itself from other programming languages by it's particularly strong emphasis on readability –code that conforms itself to known best practices/standards.
Within the Python community, well written code is said to be "Pythonic" if it adheres to the Python philosophy. People who have mastered coding in a Pythonic way are known as "Pythonistas."
The most canonical example of the tenets that distinguish un-Pythonic from Pythonic code can be found in Tim Peters famous poem, "The Zen of Python." To read it you need only open a Python prompt on your command line, and type the words, "import this."
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly. / Đẹp còn hơn xấu.
Explicit is better than implicit. / Rõ ràng tốt hơn là ngầm hiểu.
Simple is better than complex. / Đơn gi tốt hơn là phức hợp.
Complex is better than complicated. / Phức hợp là tốt hơn phức tạp.
Flat is better than nested. / Phẳng là tốt hơn lồng vào nhau.
Sparse is better than dense. / Thưa thớt tốt hơn dày đặc.
Readability counts. / Số lượng khả năng đọc.
Special cases aren't special enough to break the rules. / Các trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc.
Although practicality beats purity. / Mặc dù tính thực tế đánh bại sự thuần khiết.
Errors should never pass silently. / Những sai sót không bao giờ nên trôi qua một cách âm thầm.
Unless explicitly silenced. / Trừ khi im lặng rõ ràng.
In the face of ambiguity, refuse the temptation to guess. / Khi đối mặt với sự mơ hồ, hãy từ chối sự cám dỗ của sự phỏng đoán
There should be one-- and preferably only one --obvious way to do it. / Nên có một-- và tốt nhất là chỉ có một - cách thức đơn giản để làm điều đó.
Although that way may not be obvious at first unless you're Dutch. / Mặc dù cách đó có thể không rõ ràng lúc đầu trừ khi bạn là người Hà Lan.
Now is better than never. / Bây giờ tốt hơn là không bao giờ
Although never is often better than *right* now.
If the implementation is hard to explain, it's a **BAD** idea.
If the implementation is easy to explain, it may be a **GOOD** idea.
Namespaces are one honking great idea -- let's do more of those!
The two lines most relevant to this page are
- Readability counts
- There should be one-- and preferably only one -- obvious way to do it
Indicate seperate words in variable names using underscores
my_variable_name = True
Indicate seperate words in function names using underscores
def my_function_name():
pass
Indicate seperate words in class names using CamelCase / Chỉ ra các từ riêng biệt trong tên lớp bằng CamelCase
class MyClassName(object):
pass
Prefix a single underscore to class members/functions meant for internal use only / Bắt đầu một dấu gạch dưới duy nhất cho các thành viên / chức năng của lớp chỉ dành cho mục đích sử dụng nội bộ
class MyClassName(object):
def _internal_function(self):
pass
Use all caps to indicate constants / Sử dụng tất cả các chữ hoa để biểu thị các hằng số
class ConnectDB(object):
DB = "mysql",
USER = "Steve",
PASS = "fzHx$"
def __init__(self):
pass
Use 4 spaces per indentation level / Sử dụng 4 dấu cách cho mỗi mức thụt lề
BAD
if x is True:
print(x)
GOOD
if x is True:
print(x)
Limit the length of your lines to 79 characters in width / Giới hạn chiều dài dòng của bạn ở 79 ký tự chiều rộng
BAD
def my_function(a, b, c):
my_str = "a, b, and c contains the following values {0}, {1}, {2}".format(a, b, c)
GOOD
def my_function(a, b, c):
my_str = "a, b, and c contains the following values {0}, {1}, {2}".format(
a, b, c)
Create readable multi-line text with the use of parentheses / Tạo văn bản nhiều dòng có thể đọc được bằng cách sử dụng dấu ngoặc đơn
BAD
big_string = """This is the first line in the text \
this is the second line in the text \
this is the third line in the text"""
GOOD
big_string = (
"This is the first line in the text "
"this is the second line in the text "
"this is the third line in the text"
)
In general, try to only import one module per line / Nói chung, hãy cố gắng chỉ nhập một mô-đun trên mỗi dòng
BAD
import sys, os, requests
GOOD
import os
import sys
import requests
Avoid using a temporary variable when swapping two variables / Tránh sử dụng một biến tạm thời khi hoán đổi hai biến
BAD
c = a
a = b
b = c
GOOD
a, b = b, a
Use tuples to unpack data / Sử dụng bộ giá trị để lấy dữ liệu
BAD
li = [1, 2, 3]
a = li[0]
b = li[1]
c = li[2]
GOOD
li = [1, 2, 3]
(a, b, c) = li
Use ''.join() on an empty string to concatonate a collection of strings / Sử dụng '' .join () trên một chuỗi trống để nối một tập hợp các chuỗi
BAD
li = ['a', 'b', 'c']
result = ''
for x in li:
result += x
GOOD
li = ['a', 'b', 'c']
result = ''.join(li)
Use dict.get() to return a default value from a dictionary / Sử dụng dict.get () để trả về giá trị mặc định từ dictionary
BAD
x = None
if 'item' in my_dict:
x = my_dict['item']
else:
x = 'fallback value'
GOOD
x = my_dict.get('item', 'fallback value')
Open files using using the with statement / Mở tệp bằng câu lệnh with
BAD
f = open(path_to_file)
for line in f.readlines():
# do something...
f.close()
GOOD
with open(path_to_file) as f:
for line in f:
# do something...
# no need to call close()
Avoid repeating a variable within a compound if statement / Tránh lặp lại một biến trong câu lệnh if ghép
BAD
if name=='Tom' or name=='Sam' or name=='Ron':
pass
GOOD
if name in ('Tom', 'Sam', 'Ron'):
pass
Don't place conditional code on the same line as the colon / Không đặt mã có điều kiện trên cùng một dòng với dấu hai chấm
BAD
if item: print(item)
GOOD
if item:
print(item)
Avoid putting multiple statements on a single line / Tránh đặt nhiều câu lệnh trên một dòng
BAD
if condition: my_function(); my_other_function();
GOOD
if condition:
my_function()
my_other_function()
Use list comprehensions to create lists that are subsets of existing data / Sử dụng khả năng hiểu danh sách để tạo danh sách là tập hợp con của dữ liệu hiện có
BAD
l1 = range(1, 100)
l2 = []
for x in l1:
if is_prime(x):
l2.append(x)
GOOD
l1 = range(1, 100)
l2 = [x for x in l1 if is_prime(x)]
Use the 'in' keyword to iterate over an Iterable / Sử dụng từ khóa 'in' để lặp lại một Lặp lại
BAD
li = ['a', 'b', 'c']
index = 0
while index < len(li):
print(li[index])
index += 1
GOOD
li = ['a', 'b', 'c']
for element in li:
print(element)
Use the 'enumerate' built-in function to keep count on an Iterable / Sử dụng hàm tích hợp 'liệt kê' để tiếp tục đếm trên một Lặp lại
BAD
li = ['a', 'b', 'c']
index = 0
for item in li:
print(index, item)
index += 1
GOOD
for index, item in enumerate(li):
print(index, item)
Create a length-N list composed of the same specific item / Tạo một danh sách dài-N bao gồm cùng một mục cụ thể
BAD
four_nones = []
for x in range(1,5):
four_nones.append(None)
GOOD
four_nones = [None] * 4
Create a length-N list composed of empty lists / Tạo một danh sách dài-N bao gồm các danh sách trống
BAD
li = []
for _ in range(1, 5):
li.append([])
GOOD
li = [[] for _ in range(4)]
Use isinstance() to do object type comparisons / Sử dụng isinstance () để so sánh loại đối tượng
BAD
x = 5
if type(x) is type(1):
print('x is an int')
GOOD
x = 5
if isinstance(x, int):
print('x is an int')
For strings, lists, and tuples, use the fact that empty sequences are false / Đối với chuỗi, danh sách và bộ giá trị, hãy sử dụng thực tế là các chuỗi trống là sai
BAD
x = []
if not len(x):
print('x is false')
GOOD
x = []
if not x:
print('x is false')
Avoid using a mutable values as a default function parameter / Tránh sử dụng các giá trị có thể thay đổi làm tham số hàm mặc định
BAD
def fn(x=[]):
x.append(1)
print(x)
GOOD
def fn(x=None):
x = [] if x is None else x
x.append(1)
print(x)
Check that all items in a large set of items are true / Kiểm tra xem tất cả các mục trong một tập hợp lớn các mục có đúng không
BAD
if a and b and c and d and e and f and g and h:
print('all true')
GOOD
if all([a, b, c, d, e, f, g, h]):
print('all true')
Check if at least one item in a set of three or more items are true / Kiểm tra xem ít nhất một mục trong bộ ba mục trở lên có đúng không
BAD
if a or b or c:
print('at least one is true')
GOOD
if any([a, b, c]):
print('at least one is true')
Be careful how you use the is operator when checking for empty/unset variables.
Inherently falsy values like None, [], (), "", '', and 0 do not all mean the same thing.
Hãy cẩn thận cách bạn sử dụng toán tử is khi kiểm tra các biến empty/unset. Vốn dĩ các giá trị giả như Không, [], (), "", '' và 0 không phải tất cả đều có nghĩa giống nhau.
BAD
import random
x = random.choice([ None, [] ])
if x is not None:
print(x)
# if x=[] then print(x) will run
GOOD
import random
x = random.choice([ None, [] ])
if x:
print(x)
# neither None or [] will pass the if statment
Be aware of scope. Using the same variable name for a global and local variables can lead to errors / Hãy nhận biết về phạm vi. Sử dụng cùng một tên biến cho biến cục bộ và toàn cục có thể dẫn đến lỗi
BAD
x = 1
def fn():
print(x)
x = 2
fn() # UnboundLocalError: local variable 'x' referenced before assignment
print(x) # prints 1
GOOD
# things work as expected as long as we don't locally redfine x in the function scope
x = 1
def fn():
print(x)
y = 2
fn() # prints 1
print(x) # prints 1
# to modify the global variable x, you could do
x = 1
def fn():
global x
print(x)
x = 2
fn() # prints 1
print(x) # prints 2
Take advantage of extended slice notation to reverse a string / Tận dụng extended slice để đảo ngược một chuỗi
BAD
backward = ''
for c in reversed('hello'):
backward += c
print(backward) # 'olleh'
GOOD
# the faster albiet less readable approach is
backward = 'hello'[::-1]
# the slower but more readable approach is:
backward = ''.join(reversed('hello'))
print(backward) # 'olleh'
Counting frequency
BAD
ls = ['a', 'a', 'b', 'c', 'a']
foo = {}
for x in ls:
if x in foo:
foo[x] += 1
else:
foo[x] = 1
print(foo) # {'a': 3, 'b': 1, 'c': 1}
GOOD
from collections import Counter
ls = ['a', 'a', 'b', 'c', 'a']
foo = Counter(ls)
print(foo) # Counter({'a': 3, 'b': 1, 'c': 1})
Use for..else to run some code if the break statment is never reached. / Sử dụng for..else để chạy một số mã nếu câu lệnh break không bao giờ đạt được.
BAD
# bad example here that uses a tracking variable to determine if break has run or not
GOOD
for f in file_list:
if is_img(f):
break
else: # no break encountered
batch_process_files(file_list)
Add __repr__
to all your classes for more beautiful debugging
class Example:
def __init__(self, x):
self.x = x
def __repr__(self):
return 'Example(x={})'.format(self.x)
Use virtualenv
- don't install python packages at the system level
Take advantage of ipython/Juptyers profiling functions like %time
and %prun
to profile code.
Avoid *args
and **kwargs
unless you need them - they make function signatures hard to read and code-completion less helpful
Incorporate a linting tool like pyflakes
or pylint
into your IDE.
Learn to approach unit tests as a brain-storming exercise on how best to write your application.
In general prefer smaller individual functions dedicated to doing a single thing to larger functions that do many things.
Give every function a docstring.