# -*- coding: utf-8 -*-
from datetime import datetime
from time import sleep
from urllib.parse import parse_qs
import json
def example_1():
"""
确认自己所用的Python版本
* Python3 和 Python2 不兼容
:return:
"""
pass
def example_2():
"""
遵循PEP8风格指南
* 不要通过检测长度的方法, 如 if len(somelist) == 0, 而是 if not somelist
* 引入模块时, 应使用绝对名称, 而不是相对名称,如 from bar import foo 而不是
import foo.
* 如果一定要用相对名称, 就采用明确写法 from . import foo
:return:
"""
pass
def example_3():
"""
了解bytes,str和unicode的区别
* Python3, bytes 包含原始8位值, str的实例包含Unicode字符
* Python2, str 包含原始8位值, 而Unicode的实例包含Unicode字符
* Python3的str实例 和Python的Unicode实例都没有和特定的二进制编码形式相关联
:return:
"""
pass
def example_4():
"""
用辅助函数来取代复杂的表达式
:return:
"""
my_values = parse_qs("red=5&blue=0&green=", keep_blank_values=True)
print(my_values)
# 如果键的值是空就返回0
green = my_values.get("green", [''])[0] or 0
print(green) # 输出 0
pass
def example_5():
"""
了解切割序列的方法
:return:
"""
a = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(a[2:]) # 输出 ['c', 'd', 'e', 'f', 'g']
def example_6():
"""
在单次切片操作内, 不要同时指定start、end 和 stride(步进值)
* 如果非要用stride, 尽量采用负值(或考虑itertools的islide方法)
:return:
"""
a = ['rad', 'orange', 'yellow', 'green', 'blue', 'purple']
odds = a[::2] # 表示从头部开始, 每两个元素选取一个, 如果是负号则是从尾部开始
events = a[1::2]
print(odds) # 偶数索引
print(events) # 奇数索引
x = b'mongoose'
y = x[::-1] # 字符反转技巧, 注意仅对ASCII字有用, UTF-8等无法奏效
print(y)
def example_7():
"""
用列表推导来取代map和filter
:return:
"""
a = [1, 2, 3, 4, 5]
print([x ** 2 for x in a]) # 列表推导表达更清晰
print(list(map(lambda x: x ** 2, a)))
even_squares = [x ** 2 for x in a if x % 2 == 0]
print(even_squares)
alt = map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, a))
print(list(alt))
def example_8():
"""
不要使用含有两个以上表达式的列表推导
* 因为难以理解
:return:
"""
pass
def example_9():
"""
用生成器表达式来改写数据量较大的列表推导
:return:
"""
value = [len(x) for x in open('leecode.py')] # 问题数据量大,内存激增
print(value)
it = (len(x) for x in open('leecode.py')) # 改用生产器, 返回可迭代对象, 但注意迭代器有状态,仅能迭代一轮
while True:
try:
x = next(it)
print(x)
except StopIteration:
break
def example_10():
"""
尽量用enumerate来取代range
* 下标和序列元素都能一次获取
:return:
"""
flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']
for i, flavor in enumerate(flavor_list, 1):
print("%d: %s" % (i + 1, flavor))
def example_11():
"""
用zip函数同时遍历两个迭代器
* 比如两个list中的元素是一对一的关系
:return:
"""
names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]
longest_name = None
max_letters = 0
for name, count in zip(names, letters):
if count > max_letters:
longest_name = name
max_letters = count
print(longest_name)
def example_12():
"""
不要在for和while循环后面写else块
* Python可以这样做, 但是你不要这样做
:return:
"""
pass
def example_13():
"""
合理利用try/except/else/finally结构中的每个代码块
:return:
"""
UNDEFINED = object()
def divide_json(path):
handle = open(path, 'r+')
try:
data = handle.read()
op = json.load(data)
value = (op['numerator'], op['denominator'])
except ZeroDivisionError as e:
return UNDEFINED
else:
op['result'] = value
result = json.dumps(op)
handle.seek(0)
handle.write(result)
return value
finally:
handle.close()
def example_14():
"""
尽量用异常来表示特殊情况, 而不用返回None
* 容易让调用者写出错误的代码,到底是程序异常的None? 还是自己数据的不合理?
一个例子就是除法, 除数为0
* 解决办法之一: 使用元祖,一个放数据,一个放成功状态(但是调用者可以用_忽略不去检测,也是比较尴尬)
* 最好的解决就是抛异常给上一级
:return:
"""
def example_15():
"""
了解如何在闭包中使用外围作用域中的变量
* 获取闭包内的数据, 使用nonlocal关键字(Python2不支持,但是有解决)
:return:
"""
pass
def example_16():
"""
考虑用生成器来改写直接返回列表的函数
* yield 关键字
:return:
"""
def index_words_iter(text):
if text:
yield 0
for index, letter in enumerate(text):
if letter == ' ':
yield index + 1
text = 'apple pink origin'
result = list(index_words_iter(text))
print(result)
def example_17():
"""
在参数上面迭代时,要多加小心
* 问题时迭代器迭代一次
* 列表推导数据量大时, 内存激增
* 解决一: 使用lambda, 每次都能产生新的迭代器
* 最佳解决: 建立对象, 使用__iter__ 内置函数
:return:
"""
pass
def example_18():
"""
用数量可变的位置参数减少视觉杂讯
:return:
"""
def log(message, *values):
if not values:
print(message)
else:
values_str = ', '.join(str(x) for x in values)
print("%s: %s" % (message, values_str))
favorites = [7, 17, 99]
log("Favorite colors", *favorites) # 列表加上*号, Python 会把列表里的元素视为位置参数
def example_19():
"""
用关键字参数来表达可选行为
* 一个除法函数, 谁是除数? 谁是被除数?
:return:
"""
pass
def example_20():
"""
用None和文档字符串来描述具有动态默认值的参数
:return:
"""
def log(message, when=None):
"""
:param message:
:param when: datetime of when the message occurred.
Default to the present time.
:return:
"""
when = datetime.now() if when is None else when
print('%s: %s' % (when, message))
log('Hi there!')
sleep(0.1)
log('Hi again!')
def example_21():
"""
只能用以关键字形式指定的参数来确保代码清晰
:return:
"""
def safe_division(number, divisor, ignore_overflow=False, ignore_zero_division=False):
try:
return number / divisor
except OverflowError:
if ignore_overflow:
return 0
else:
raise
except ZeroDivisionError:
if ignore_zero_division:
return float("inf")
else:
raise
# 调用者可以根据自己的具体需要, 用关键字来覆盖Boolean标志的默认值, 以便跳过相关的错误
safe_division(1, 10 ** 500, ignore_overflow=True)
safe_division(1, 0, ignore_zero_division=True)
if __name__ == '__main__':
example_18()
# example_5()
# example_20()
# example_21()
“年轻时,我没受过多少系统教育,但什么书都读。读得最多的是诗,包括烂诗,我坚信烂诗早晚会让我邂逅好诗。”
by. 马尔克斯