Effective Python (Pythonic Thinking)

  • Know the differences Between bytes,str and unicode

In Python 3, there are two types that represent sequences of characters: bytes and str. Instances of bytes contain raw 8-bit values. Instances of str contain Unicode characters. 

# to_str
def to_str(bytes_or_str):
    if isinstance(bytes_to_str, bytes):
        value = bytes_or_str.decode('utf-8')
    else:
        value = bytes_or_str
    return value    # Instance of str

# to_bytes
def to_bytes(bytes_or_str):
    if isinstance(bytes_to_str, str):
        value = bytes_to_str.encode('utf-8')
    else:
        value = bytes_to_str
    return value    # Instance of bytes

In Python 2, there are two types that represent sequences of characters: str andunicode. In contrast to Python 3, instances of str contain raw 8-bit values. Instances ofunicode contain Unicode characters. 

# to_unicode
def to_unicode(unicode_or_str):
    if isinstance(unicode_or_str, str):
        value = unicode_or_str.encode('utf-8')
    else:
        value = unicode_or_str
    return value    # Instance of unicode

# to_str
def to_str(unicode_or_str):
    if isinstance(unicode_or_str, unicode):
        value = unicode_or_str.decode('utf-8')
    else:
        value = unicode_or_str
    return value    # Instance of str

    如果你要读取/写入二进制数据至文件中,请使用”rb“或者”wb“:    

import os
with open('/tmp/random.bin', 'wb') as f:
    f.write(os.urandom(10))


  • Use List Comprehensions Instead of map and filter (用列表解析代替map和filter)

a = [1, 2, 3, 4]
squares = [x ** 2 for x in a]
squares = map(lambda x: x ** 2, a)

even_squares = [x ** 2 for x in a if x % 2 == 0]
alt = map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, a))

# 对调字典的key与value
chile_ranks = {'ghost': 1, 'habanero': 2, 'cayenne': 3}
rank_dict = {rank: name for name, rank in chile_ranks.items()}
chile_len_set = {len(name) for name in rank_dict.values()}


  • Consider Generator Expressions for Large Comprehensions(用生成器表达式代替大的列表解析)
value = [len(x) for x in open('/tmp/my_file.txt')]
print(value)

it = (len(x) for x in open('/tmp/my_file.txt'))
print(next(it))

# 生成器表达式可以由另外一个生成器表达式构成
roots = ((x, x**0.5) for x in it)
print(next(roots))


  • Prefer enumerate Over range 
# 当迭代一个列表,同时想知道当前元素的索引(计数)时;使用enumerate而不是range
flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']

# use range
for i in range(len(flavor_list)):
    print('%d: %s' % (i, flavor_list[i]))
# use enumerate
for i, flavor in enumerate(flavor_list):    # enumerate(flavor_list, 1)可为enumerate指定开始计数值
    print('%d: %s' % (i, flavor))


  • Use zip to Process Iterators in Parallel 
# 使用zip并行处理迭代器
names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]

max_letters = 0
for name, count in zip(names, letters):
    if count > max_letters:
        longest_name = name
        max_letters = count

# 注意:在Python3中zip是一个元组生成器;在Python2中zip是一个由元组组成的列表。


  • Avoid else Blocks After for and while Loops 
# 避免在for与while循环之后使用else
# 1,在没有break的for/while循环结束后,会马上执行else中的语句
# 2,避免在循环之后使用else,因为else不确定是否执行
for i in in range(5):
    print i
else:
    print 'else run'
    
for i in range(5):
    break
else:
    print 'else not run'


  • Take Advantage of Each Block in try/except/else/finally
# 使用finally 去可靠的关机文件句柄、socket等
handle = open('/tmp/random_data.txt')    # May raise IOError
try:
    data = handle.read()    # May raise UnicodeDecodeError
finally:
    try:
        handle.close()    # Always runs after try
    except Exception:
        pass

# 使用else 减少try block里面的代码量、提高可读性
# 如:从字符串中加载一个json dict并返回某个key的value
def load_json_key(data, key):
    try:
        result_dict = json.loads(data)    # May raise ValueError
    except ValueError as e:
        raise KeyError from e
    else: 
        return result_dict[key]    # May raise KeyError

# 
UNDEFINED = object()

def divide_json(path):
    handle = open(path, 'r+')    # May raise IOError
    try:
        data = handle.read()    # May raise UnicodeDecodeError
        op = json.loads(data)    # May raise ValueError
        value = (op['numerator'] / op['denominator'])    # May raise ZeroDivisonError
    except ZeroDivisionError as e:
        return UNDEFINED
    else:
        op['result'] = value
        result = json.dumps(op)
        handle.seek(0)
        handle.write(result)    # May raise IOError
        return value
    finally:
        try:
            handle.close()    # Always runs
        except Exception:
            pass








你可能感兴趣的:(Effective Python (Pythonic Thinking))