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': '[email protected]'}, {'name': 'lily', 'email': '[email protected]'}]
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值.

# 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__方法

# 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

猜你喜欢

转载自www.cnblogs.com/allen2333/p/9140157.html