1, *
分割字符串
_list = ['name', 'age', '2020', '10', '10']
name, age, *years = _list
print(name)
print(age)
print(years)
# output:
# name
# age
# ['2020', '10', '10']
2, *
,**
函数传参
args = ['csdn', 100, 'https://www.youkuaiyun.com/']
kwargs = {
'name': 'csdn',
'age': 100,
'url': 'https://www.youkuaiyun.com/'
}
def print_info(name, age, url):
print(name)
print(age)
print(url)
print_info(*args)
print_info(**kwargs)
# output:
# csdn
# 100
# https://www.youkuaiyun.com/
# csdn
# 100
# https://www.youkuaiyun.com/
3, Filter
列表过滤
- 过滤None值
_list = [0, 1, None, 'None', {}, [], '']
new_list = filter(lambda x: x, _list)
print(list(new_list))
# output:
# [1, 'None']
- 过滤不符合条件的值
_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
new_list = filter(lambda x: x > 6, _list)
print(list(new_list))
# output:
# [7, 8, 9]
4, Reduce
列表计算
- 实现列表每个元素相加/乘
from functools import reduce
_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(reduce(lambda x, y: x + y, _list))
print(reduce(lambda x, y: x * y, _list))
# output:
# 45
# 362880
5, 列表推导式
列表推导式也可以完成 filter
的功能
_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
new_list = [i for i in _list if i > 6]
print(new_list)
# output:
# [7, 8, 9]
filter 和列表推导式性能对比:
import time
from functools import reduce
_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
filter_l = []
times = 1000000
for i in range(times):
start = time.time()
new_list = filter(lambda x: x > 6, _list)
end = time.time()
filter_l.append(end - start)
print(reduce(lambda x, y: x + y, filter_l) / times)
# output:
# 2.3841428756713868e-07
import time
from functools import reduce
_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
comprehensions_l = []
times = 1000000
for i in range(times):
start = time.time()
new_list = filter(lambda x: x > 6, _list)
end = time.time()
comprehensions_l.append(end - start)
print(reduce(lambda x, y: x + y, comprehensions_l) / times)
# output:
# 2.3479533195495605e-07
两种方法过滤列表性能差不多,但是列表推导式语法更为简洁。
6, slots 魔法
一般来说,类使用一个字典保存实例的属性。
class A(object):
def __init__(self, name, age):
self.name = name
self.age = age
class B(object):
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
a = A(name='a', age='100')
print(dir(A))
print(dir(B))
print(a.__dict__)
# output:
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'age', 'name']
# {'name': 'a', 'age': '100'}
从输出上,可以明显看出 class B
少了一个 __dict__
属性,这是由于 B
定义了 __slots__
,告诉 Python 不要生成 __dict__
, 从而减少了内存的使用。
7, defaultdict
为字典保留多个值
from collections import defaultdict
colours = (
('Yasoob', 'Yellow'),
('Ali', 'Blue'),
('Arham', 'Green'),
('Ali', 'Black'),
('Yasoob', 'Red'),
('Ahmed', 'Silver'),
)
favourite_colours_l = defaultdict(list)
favourite_colours_s = defaultdict(str)
for name, colour in colours:
favourite_colours_l[name].append(colour)
favourite_colours_s[name] += colour + ' '
print(dict(favourite_colours_l))
print(dict(favourite_colours_s))
# Output:
# {'Yasoob': ['Yellow', 'Red'], 'Ali': ['Blue', 'Black'], 'Arham': ['Green'], 'Ahmed': ['Silver']}
# {'Yasoob': 'Yellow Red ', 'Ali': 'Blue Black ', 'Arham': 'Green ', 'Ahmed': 'Silver '}
8, defaultdict
为字典嵌套赋值
import collections
import json
tree = lambda: collections.defaultdict(tree)
some_dict = tree()
some_dict['colours']['favourite'] = "yellow"
print(json.loads(json.dumps(some_dict)))
# Output:
# {'colours': {'favourite': 'yellow'}}
9, enumerate
遍历计数
my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 1):
print(c, value)
# Output:
# (1, 'apple')
# (2, 'banana')
# (3, 'grapes')
# (4, 'pear')
10, dir
列举对象的所有属性和方法
from collections import defaultdict
favourite_colours = defaultdict(str)
print(dir(favourite_colours))
# Output:
# ['__class__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__missing__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'default_factory', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
11, else
从句
try else
从句会在没有抛出错误时执行
try:
print('I am sure no exception is going to occur!')
except Exception:
print('exception')
else:
# 这里的代码只会在try语句里没有触发异常时运行,
# 但是这里的异常将不会被捕获
print('This would only run if no exception occurs. And an error here '
'would NOT be caught.')
finally:
print('This would be printed in every case.')
# Output: I am sure no exception is going to occur!
# This would only run if no exception occurs.
# This would be printed in every case.
for else
从句会在循环正常结束时执行
max_ = 100
for i in range(100):
if i > max_:
raise Exception(f'i > {max_}')
else:
print('not raise any error')
# Output:
# not raise any error
12, 协程
Python中的协程和生成器很相似但又稍有不同。主要区别在于: 生成器是数据的生产者 协程则是数据的消费者
- 生成器
def range_(num):
for i in range(num):
yield i
for i in range_(10):
print(i)
# Output:
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
- 协程, python 实现 grep
def search(key):
while True:
line = (yield)
print(line if key in line else 'No')
s = search('python')
next(s) # 启动协程
s.send('hello world')
s.send('hello java')
s.send('hello python')
s.send('hello php')
s.close() # 关闭协程
s.send('close?')
# Output:
# No
# No
# hello python
# No
# Traceback (most recent call last):
# File "/home/kaige/Github/gov/cn12348/tools/test.py", line 14, in <module>
# s.send('close?')
# StopIteration
13, 函数缓存
当一个I/O密集的函数被频繁使用相同的参数调用的时候,函数缓存可以节约时间。
import time
from functools import lru_cache
@lru_cache(maxsize=32)
def func(n):
return n ** 10
def func_nocache(n):
return n ** 10
start = time.time()
[func(10) for _ in range(1000000)]
end = time.time()
print(end - start)
start = time.time()
[func_nocache(10) for _ in range(1000000)]
end = time.time()
print(end - start)
# Output:
# 0.06982040405273438
# 0.23273038864135742
经过测试,使用函数缓存,在使用相同参数调用同一函数时,至少能提高4倍效率。