过滤掉列表List中的负数—列表解析式
import random
List = random.sample(range(-100, 100), 10)
new_List = [x for x in List if x >= 0]
筛选出Dict中值不为空的项—字典解析式
Dict = {'a': 79, 'b': None, 'c': 12,}
new_Dict = {k:v for k, v in Dict.items() if v }
给元祖中的每个元素命名,提高程序的可读性
from collections import namedtuple
Student = namedtuple('Student', ['name', 'age', 'sex', 'email'])
one_student = Student('Rick', '18', 'male', 'loveweihaitong@foxmail.com')
# one_student.name --> Rick
给可迭代对象中的每个元素命名(解构赋值)
student = ['Tom', 18, 'male']
name, age, gender = student
print(name, age, gender)
# Tom 18 male
num_list = [100, 19, 20, 98]
first, *left_num_list, last = num_list
print(first, left_num_list, last)
# 100 [19, 20] 98
student = [['Tom', (98, 96, 100)], ['Jack', (98, 96, 100)]]
for name, (first, second, third) in student:
print(name, first, second, third)
# Tom 98 96 100
# Jack 98 96 100
统计随机序列中出现频率最高的三个元素,并统计它们出现的次数
from collections import Counter
from random import randint
random_sequence = [randint(0, 5) for _ in range(10)]
# [1, 5, 2, 4, 3, 0, 5, 5, 1, 0]
result = Counter(random_sequence)
# Counter({5: 3, 1: 2, 0: 2, 2: 1, 4: 1, 3: 1})
new_result = result.most_common(3)
# [(5, 3), (1, 2), (0, 2)]
反向遍历集合
colors = ['red', 'green', 'blue', 'yellow']
for i in range(len(colors)-1, -1, -1):
print(colors[i])
# better
for color in reversed(colors):
print(color)
快速找到字典中的公共键
from random import randint
from functools import reduce
# d1 -> {'库里': 29, '汤普森': 14, '杜兰特': 25, '格林': 11, '帕楚里亚': 22, '欧文': 17, '詹姆斯': 28}
d1 = {x: randint(10, 30) for x in ['库里', '汤普森', '杜兰特', '格林', '帕楚里亚', '欧文', '詹姆斯']}
d2 = {x: randint(10, 30) for x in ['汤普森', '杜兰特', '格林', '麦基', '香波特', '詹姆斯', '库里', '韦德']}
d3 = {x: randint(10, 30) for x in ['格林', '杜兰特', '利文斯顿', '库里', '香波特', '詹姆斯', '汤普森', '韦德']}
# 如果你想映射一个序列到另一个序列,直接调用map函数。
# map(f(x),Itera) 第一个参数为某个函数,第二个为可迭代对象。
Set = map(dict.keys, [d1, d2, d3])
# 使用reduce函数,取所有函数的keys集合的交集, 并集用|,差集用-
reduce(lambda a, b: a & b, Set)
# {'库里', '汤普森', '杜兰特', '格林', '詹姆斯'}
合并字典
query = {'id': 1, 'render_fast': True}
post = {'email': 'j@j.com', 'name': 'Joff'}
route = {'id': 271, 'title': 'Fast_apps'}
# 这里面如果有相同的键,后面键的值会覆盖前面的值,例如本例中的id。
merge_dic = {**query, **post, **route}
# {'id': 271, 'render_fast': True, 'email': 'j@j.com', 'name': 'Joff', 'title': 'Fast_apps'}
使用defaultdict实现树结构
defaultdict 允许我们通过工厂方法来动态创建不存在的属性
from collections import defaultdict
my_dict = defaultdict(lambda: 'Default Value')
my_dict['a'] = 42
print(my_dict['a'])
print(my_dict['b'])
# 42 Default Value
用defaultdict来构造一颗树形数据结构
from collections import defaultdict
import json
def tree():
"""
Factory that creates a defaultdict that also uses this factory
"""
return defaultdict(tree)
root = tree()
root['Page']['Python']['defaultdict']['Title'] = 'Using defaultdict'
root['Page']['Python']['defaultdict']['Subtitle'] = 'Create a tree'
root['Page']['Java'] = None
print(json.dumps(root, indent=4))
"""
{
"Page": {
"Python": {
"defaultdict": {
"Subtitle": "Create a tree",
"Title": "Using defaultdict"
}
},
"Java": null
}
}
"""
Switch/Case 实现
函数式编程,很好的解耦每个case中的业务逻辑。提高复用性和可维护性
# pythonic: 巧用字典的数据结构的代码代替通常switch语句,完成case的功能。
def get_sunday():
return 'sunday'
def get_monday():
return 'monday'
def get_tuesday():
return 'tuesday'
def get_default():
return 'unknown'
def switcher(arg):
switch = {
0: get_sunday,
1: get_monday,
2: get_tuesday,
}
return switch.get(arg, get_default)()
day = 9
day_name = switcher(day)
print(day_name)
使用iter()连续调用函数
blocks = []
while True:
block = f.read(32)
if block == '':
break
blocks.append(block)
# better
blocks = []
for block in iter(partial(f.read, 32), ''):
blocks.append(block)
iter 接受两个参数时. 第一个参数是一个可调用对象(函数), 第二个参数是边界值, 当可调用对象返回这个值时, 就会抛出StopIteration
使用字典进行计数
colors = ['red', 'green', 'red', 'blue', 'green', 'red']
d = {}
for color in colors:
if color not in d:
d[color] = 0
d[color] += 1
# better
d = {}
for color in colors:
d[color] = d.get(color, 0) + 1
d = defaultdict(int)
for color in colors:
d[color] += 1
使用ignored() 代替 pass exception
try:
os.remove('somefile.tmp')
except OSError:
pass
# better
with ignored(OSError):
os.remove('somefile.tmp')
使用上下文管理器减少临时变量
# Temporarily redirect standard out to a file and then return it to normal
with open('help.txt', 'w') as f:
oldstdout = sys.stdout
sys.stdout = f
try:
help(pow)
finally:
sys.stdout = oldstdout
# better
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
@contextmanager
def redirect_stdout(fileobj):
oldstdout = sys.stdout
sys.stdout = fileobj
try:
yield fieldobj
finally:
sys.stdout = oldstdout
生成器函数实现可迭代对象
class PrimeNumbers(object):
def __init__(self, *, start, end):
self.start = start
self.end = end
def isPrimeNum(self, k):
if k < 2:
return False
for i in range(2, k):
if k % i == 0:
return False
return True
def __iter__(self):
for k in range(self.start, self.end + 1):
if self.isPrimeNum(k):
yield k
pn = PrimeNumbers(start=1, end=30)
print(list(pn))
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
反向迭代
class FloatRange(object):
def __init__(self, start, end, step=0.1):
self.start = start
self.end = end
self.step = step
# 正向迭代器
def __iter__(self):
t = self.start
while t <= self.end:
yield t
t += self.step
# 反向迭代器
def __reversed__(self):
t = self.end
while t >= self.start:
yield t
t -= self.step
floatRange = FloatRange(1.0, 4.0, 0.5)
# 正向迭代器实例
print(list(floatRange))
# [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
# 反向迭代器实例
print(list(reversed(floatRange)))
# [4.0, 3.5, 3.0, 2.5, 2.0, 1.5, 1.0]
使用itertools里的islice()对迭代器做切片操作
"""对迭代器做切片操作"""
from itertools import islice
print(list(islice(floatRange, 2, 6)))
# [2.0, 2.5, 3.0, 3.5]
在一个for语句中迭代多个可迭代对象
from random import randint
from itertools import chain
chinese = [randint(60, 100) for _ in range(10)]
math = [randint(60, 100) for _ in range(10)]
english = [randint(60, 100) for _ in range(10)]
# chinese -> [98, 65, 99, 94, 97, 74, 95, 64, 90, 87]
# math -> [88, 98, 63, 73, 80, 73, 65, 79, 74, 64]
# english -> [95, 87, 61, 65, 62, 94, 91, 88, 72, 78]
# 并行
total = []
# zip()函数可将多个迭代对象合并,每次迭代返回一个元祖
for c, m, e in zip(chinese, math, english):
total.append(c + m + e)
# total -> [281, 250, 223, 232, 239, 241, 251, 231, 236, 229]
# 串行
total = []
# itertools中chain()可以进行多个迭代对象的连接
print(list(chain(chinese, math, english)))
# [98, 65, 99, 94, 97, 74, 95, 64, 90, 87, 88, 98, 63, 73, 80, 73, 65, 79, 74, 64, 95, 87, 61, 65, 62, 94, 91, 88, 72, 78]
使用 itertools.combinations 求列表或生成器中指定数目的元素不重复的所有组合
x = itertools.combinations(range(4), 3)
print(list(x))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
使用itertools.combinations_with_replacement 求允许重复元素的组合
x = itertools.combinations_with_replacement(range(4), 3)
print(list(x))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 2), (0, 2, 3), (0, 3, 3), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 2), (1, 2, 3), (1, 3, 3), (2, 2, 2), (2, 2, 3), (2, 3, 3), (3, 3, 3)]
使用itertools.compress 按照真值表筛选元素
x = itertools.compress(range(5), (True, False, True, True, False))
print(list(x))
[0, 2, 3]
使用 itertools.cycle 循环指定的列表和迭代器
x = itertools.cycle('ABC')
print(list(itertools.islice(x, 0, 10, 1)))
['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A']
使用 itertools.dropwhile 按照真值函数丢弃掉列表和迭代器前面的元素
x = itertools.dropwhile(lambda e: e < 5, range(10))
print(list(x))
[5, 6, 7, 8, 9]
使用 itertools.filterfalse 保留对应真值为False的元素
x = itertools.filterfalse(lambda e: e < 5, (1, 5, 3, 6, 9, 4))
print(list(x))
[5, 6, 9]
使用 itertools.groupby 按照分组函数的值对元素进行分组
x = itertools.groupby(range(10), lambda x: x < 5 or x > 8)
for condition, numbers in x:
print(condition, list(numbers))
True [0, 1, 2, 3,4]
False [5, 6, 7,8]
True [9]
拆分含有多种分隔符的字符串
import re
s = 'ab;gdgfdg|iuiu,sddsd|iweoiru\t8998;rst,qwq\tererer'
# 正则来对字符串进行选择
res = re.split('[,;\t|]+', s)
# ['ab', 'gdgfdg', 'iuiu', 'sddsd', 'iweoiru', '8998', 'rst', 'qwq', 'ererer']
使用装饰器来缓存数据
"""
题目一: 斐波那契数列(Fibonacci Sequence),又称黄金分割数列,
指的是这样一个数列:1,1,2,3,5,8,13,21,.....
这个数列从第三项开始,每一项都等于前两项之和。求数列第N项
"""
def memo(func):
cache = {}
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
@memo
def fibonacci(n):
if n <= 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
import sys
sys.setrecursionlimit(1000000)
print(fibonacci(50))
# 20365011074
"""
题目二: 一个共有10个台阶的楼梯,从下面走到上面,一次只能迈1-3个台阶,
并且不能后退,走完这个楼梯共有多少种方法。
"""
@memo
def climb(n, steps):
count = 0
if n == 0:
count = 1
elif n > 0:
for step in steps:
count += climb(n - step, steps)
return count
print(climb(10, (1, 2, 3)))
# 274
属性可以修改的函数装饰器
from functools import wraps
import time
from random import randint
import logging
def warn(timeout):
timeout = [timeout]
def decorator(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
used = time.time() - start
if used > timeout[0]:
msg = '%s : %s > %s' % (func.__name__, used, timeout[0])
logging.warn(msg)
return res
def setTimeout(k):
nonlocal timeout # python 3
# timeout = k
timeout[0] = k
wrapper.setTimeout = setTimeout
return wrapper
return decorator
@warn(1.5)
def rand():
print('In test')
while randint(0, 1):
time.sleep(0.5)
for _ in range(30):
rand()
# In test
# In test
# WARNING:root:rand : 1.5010855197906494 > 1.5
# In test
# In test
# .........