True/False判定

FalseTrue
FalseTrue (== 1)
0, 0.0非0数值
(), [], {}, set()含有元素的容器
None

在进行判断的时候直接根据上表进行判断,

if x:
    ...

避免进行类似判断,

if x == True:
  ...

if x is not None and len(x) > 0:
  ...

但是在某些情况下如果要再进一步区分就需要显示指定,


if x is None:
    ...
elif len(x) == 0:
    ...
else:
    ...

字符串

字符串拼接

合理选择%,format方法。format方法支持更多特性,适用更多场景。

# 格式化参数较少,通过字符串格式化进行拼接
msg = 'hello %s' % name

# 格式化参数较多,且当前context存在包含格式化参数的dict,
msg = 'today is %{today}s, tommorow is %{tomorrow}s' % {'today': today, 'tomorrow': tomorrow}

# 格式化参数较多,且当前context不存在包含格式化参数的dict,通过字符串format函数进行拼接
msg = 'today is %{today}s, tommorow is %{tomorrow}s'.format(today=today, tomorrow=tomorrow)

从列表构建字符串

numbers = [1, 2, 3, 4, 5]
# 用,分割
result = ','.join(numbers)
# 用,分割,且对列表中数字进行处理
result = ','.join(x*x for x in numbers)

长字符串定义

推荐将字符串定义在()内,让Python自动进行字符串拼接

# 'foobar'
result = ('foo'
          'bar')

容器

list

  • 通过enumerate访问下标及元素
colors = ['red', 'green', 'blue']
for idx, color in enumerate(colors):
    print idx, color
  • 使用xrange而不是range,range会返回list,xrange返回xrange object
for i in xrange(100):
  ...
  • 优先使用list comprehension而不是map
numbers = [1, 2, 3, 4, 5]
numbers = [x * x for x in numbers]
numbers = map(lambda x: x * x, numbers)

set

  • 有默认元素时可用{}进行初始化
empty_set = set()
color_set = {'red', 'green', 'blue'}

dict

  • 判断元素是否在容器中,使用in,而不是has_key
'A' in char_dict
  • 使用collections.defaultdict给dict设置默认值
from collections import defaultdict
words = defaultdict(list)
words['en'].append('a')

函数

  • 避免函数默认参数使用可变容器,默认参数只会创建一次,多次进入函数会实际会获取到不同的默认值
def foo(values=[]):
    ...
    values.append('a')
    ...

generator

  • 定义generator,返回数据时使用yield
def reverse(data):
    for index in xrange(len(data)-1, -1, -1):
        yield data[index]
  • 适当使用generator,在不需要创建list保存数据时可以使用generator expression
numbers = [1, 2, 3, 4, 5]
# list comprehension
sum = sum([x * x for x in numbers])
# generator
sum = sum(x * x for x in numbers)

decorator

  • staticmethod, classmethod, module function使用

    • 如果一组函数可以被归类或归组,则推荐使用staticmethod定义在类中
    • 如果函数需要访问类对象,则推荐使用classmethod
    • 其它情况下再可考虑直接定义成module function
  • 记录函数运行时间

import time

def tracker(func):
    def _tracker(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print 'func %s cost %s' % (func.__name__, time.time() - start)
        return result 

@tracker
def foo():
    pass
  • 强制验证参数类型
  • 缓存函数操作结果
  • 其它公共统一逻辑处理

排序

  • 对列表进行默认排序
numbers = [2, 1, 3, 5, 4]
# 在list上直接进行修改
numbers.sort()
# 不改变原数据,返回新列表
sorted(numbers)
  • 指定排序函数
items = [('A', 1), ('B', 11), ('B', 10)]
# 按item第2个元素进行排序
items.sort(key=lambda x: x[1])
  • 根据多个元素进行排序,使用operator.itemgetter
items = [('A', 1), ('B', 11), ('B', 10), ('A', 0)]
# 先比较第一个元素,再比较第二个元素,利用了tuple比较规则
items.sort(key=itemgetter(0, 1))
  • 更复杂的排序比较条件可以通过定义更复杂的key function来进行处理
class K(object):
    def __init__(self, obj):
        self.obj = obj
    def __lt__(self, other):
        return self.obj < other
    def __gt__(self, other):
        return self.obj > other
    def __ne__(self, other):
        return self.obj != other

numbers = [2, 1, 3, 5, 4]
sorted(numbers, key=K)
  • 或者可以自定cmp函数,并通过functools.cmp_to_key转化成key function,
from functools import cmp_to_key
def cmp(x, y):
    return x - y
numbers = [2, 1, 3, 5, 4]
sorted(numbers, key=cmp_to_key(cmp))

其它

  • 行末注意不要添加多余逗号,否则会无意识下使得变量类型别成tuple,导致后续逻辑运行时异常
# name is num
num = 100

# name is tuple
num = 100,
  • 需要明确判断变量是否为None时用is,
if val is None:
    ...
    
if val is not None:
    ...
  • 用is进行identity判断,==进行equality判断
a = 'foobar'
b = ''.join(('foo', 'bar'))

# True
a == b

# False
a is b
  • 除法 //,省略掉小数部分
# 0
3 // 2

# 1.0
3.3 // 2
  • 定义singleton
class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
           cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance
  • 类型检查用isinstance,但实际编码中最好不要一类类型检查,在继承关系当中最好通过overridde is_xxx()系列函数来进行判断

Reference