Python - 編程技巧,語法糖,黑魔法,pythonic

參考,搬運

  1. http://python-web-guide.readthedocs.io/zh/latest/idiom/idiom.html
  2. 待定

1. Python支持鏈式比較

# bad
a = 5
if a > 1 and a < 7:
    pass
# good
if 1 < a < 7:
    pass

2. Python交換變量

# bad
x = 10
y = 5
tmp = x
x = y
y = tmp

# good
x = 10
y = 5
x, y = y, x

3. Python中替代三目運算符?:

# bad
a = 10
b = 5
if a > b:
    c = a
else:
    c = b
# good
c = a if a > b else b

4. 格式化字符時多使用format函數

# bad
name = "tony"
age = 100
str = "myname : " + name + " my age : " + str(age)
str1 = "myname : %s my age : %d" % (name, age)
# good
str2 = "myname : {} my age {}".format(name, age)

5. 使用列表或者字典comprehension(推導式)

# bad
mylist = range(20)
odd_list = []
for e in mylist:
    if e % 2 == 1:
        odd_list.append(e)
# good
odd_list = [e for e in mylist if e % 2 == 1]

# bad
user_list = [{'name': 'lucy', 'email': 'lucy@g.com'}, {'name': 'lily', 'email': 'lily@g.com'}]
user_email = {}
for user in user_list:
    if 'email' in user:
        user_email[user['name']] = user['email']
# good
{user['name']: user['email'] for user in user_list if 'email' in user}

6. 條件判斷時,避免直接和True, False, None進行比較(==)

# bad
if l == []:
    pass
# good
if l:    # 實際調用l.__len__() == 0
    pass

# bad
if something == None:
# good, None 是單例對象
if something is None:

7. 使用enumerate代替for循環中的index變量訪問

# bad
my_container = ['lily', 'lucy', 'tom']
index = 0
for element in my_container:
    print '{} {}'.format(index, element)
    index += 1

# good
for index, element in enumerate(my_container):
    print '%d %s' % (index, element)

8. 避免使用可變(mutable)變量做爲函數參數的默認初始化值

# bad
def function(l = []):
 l.append(1)
 return l

 print function()
 print function()
 print function()

 # print
 [1]
 [1, 1]
 [1, 1, 1]

 # good 使用None做爲可變對象佔位符
 def function(l=None):
     if l is None:
         l = []
     l.append(1)
     return l

9. 一切皆對象

# bad
def print_addition_table():
    for x in range(1, 3):
        for y in range(1, 3):
            print(str(x + y) + '\n')

def print_subtraction_table():
    for x in range(1, 3):
        for y in range(1, 3):
            print(str(x - y) + '\n')

def print_multiplication_table():
        for x in range(1, 3):
            for y in range(1, 3):
                print(str(x * y) + '\n')

def print_division_table():
    for x in range(1, 3):
        for y in range(1, 3):
            print(str(x / y) + '\n')

print_addition_table()
print_subtraction_table()
print_multiplication_table()
print_division_table()

# good, python一切都是對象,能夠函數做爲參數,相似技巧能夠用來簡化代碼
import operator as op

def print_table(operator):
    for x in range(1, 3):
        for y in range(1, 3):
            print(str(operator(x, y)) + '\n')

for operator in (op.add, op.sub, op.mul, op.div):
    print_table(operator)

10. 防護式編程EAFP vs LBYL

# LBYL
def getPersonInfo(person):
    if person == None:
        print 'person must be not null!'
    print person.info

# EAFP
def getPersonInfo(person):
    try:
        print person.info
    except NameError:
        print 'person must be not null!'

11. 用dict對象完成switch...case...的功能

# bad
def apply_operation(left_operand, right_operand, operator):
    if operator == '+':
        return left_operand + right_operand
    elif operator == '-':
        return left_operand - right_operand
    elif operator == '*':
        return left_operand * right_operand
    elif operator == '/':
        return left_operand / right_operand
# good
def apply_operation(left_operand, right_operand, operator):
    import operator as op
    operator_mapper = {'+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv}
    return operator_mapper[operator](left_operand, right_operand)

12. 訪問tuple的數據項時,能夠用namedtuple代替index的方式訪問

# bad
rows = [('lily', 20, 2000), ('lucy', 19, 2500)]
for row in rows:
    print '{}`age is {}, salary is {} '.format(row[0], row[1], row[2])

# good
from collections import  namedtuple
Employee = namedtuple('Employee', 'name, age, salary')
for row in rows:
    employee = Employee._make(row)
    print '{}`age is {}, salary is {} '.format(employee.name, employee.age, employee.salary)

13. 用isinstance來判斷對象的類型

下面的代碼是計算一個對象的長度值,若是是序列類型(str,list,set,dict)的, 直接調用len方法,若是是True, False, None則返回1,若是是數值的,則返回其int值.html

# bad
def get_size(some_object):
    try:
        return len(some_object)
    except TypeError:
        if some_object in (True, False, None):
        return 1
    else:
        return int(some_object)

print(get_size('hello'))
print(get_size([1, 2, 3, 4, 5]))
print(get_size(10.0))

# good
def get_size(some_object):
    if isinstance(some_object, (list, dict, str, tuple)):
        return len(some_object)
    elif isinstance(some_object, (bool, type(None))):
        return 1
    elif isinstance(some_object, (int, float)):
        return int(some_object)

14. 用with管理操做資源的上下文環境

上下文協議須要實現__enter__和__exit__方法python

# bad
class Connection(object):
def execute(self, sql):
    raise Exception('ohoh, exception!')

def close(self):
    print 'closed the Connection'

try:
    conn = Connection()
    conn.execute('select * from t_users')
finally:
    conn.close()

# good
class Connection(object):
def execute(self, sql):
    raise Exception('ohoh, exception!')

def close(self):
    print 'closed the Connection'

def __enter__(self):
    return self

def __exit__(self, errorType, errorValue, error):
    self.close()

with Connection() as conn:
    conn.execute('select * from t_users')

15. 使用generator返回耗費內存的對象

# bad
def f():
    # ...
    return biglist

# bad
def f():
    # ...
    return biglist

# good
def f():
    # ...
    for i in biglist:
        yield i
相關文章
相關標籤/搜索