生成器和迭代器
list的一个问题是,如果使用range生成一个较大的list,而在使用的时候只使用1个或前几个,就会造成大量的浪费。(python2)
生成器
是一种可以对其进行迭代的程序(通常是for循环),但是它的值只需要延迟产生(lazily).
- method one:
def lazy_range(n):
i = 0
while i < n:
yield i
i += 1
for i in lazy_range(10):
print(i)# dosomethingwith(i)
在python3中range本身就是lazily的。
⚠️延迟的缺点是,你只能通过生成器迭代一次,如果需要多次迭代某个对象,你就需要每次都重新创建一个生成器,或者使用list。
- method two:
使用包含在圆括号中的for语句解析:
lazy_evens_below_20 = (i for i in range(20) if i%2== 0)
print(lazy_evens_below_20)
随机性
import random
random.random()#生成0-1之间均匀分布的随机数,是最常用的随机函数
random.seed(x)#设置随机数种子
random.random()#两次设置相同的随机数种子得到的结果一致
random.randrange(n)#返回从range(n)中[0:n-1]中随机选取
random.randrange(x,y)#返回从range(x,y)中[x,y-1]中随机选取
up_to_tem = list(range(10))#注意这里直接使用range(10)不可以一定要强制list()才行
random.shuffle(up_to_tem)#shuffle对list中的元素随机重新排列
random.choice(up_to_tem)#注意只能随机选取一个元素
#不重复选取
random.sample(list,num)#list:待选取list num:想要选取的元素个数
#重复选取
#多次调用choice即可
four_with_replacement = [random.choice(list(range(10))) for _ in range(4)]
#使用_占位,没有实际意义
正则表达式
import re
#正则的package
re.match("a","cat")#cat是以a为开头吗?
re.search("c"."dog")#dog中是否有一个字符是c?
re.split("[ab]","carbs")#分割掉a,b剩余的字符
re,sub("[0-9]","-","R2D2")#将用虚线进行位的替换
枚举
有时候,想在一个list上进行迭代,并且同时使用它的元素和索引
在一个已知的list上面进行迭代
for i,document in enumerate(documents):
do_something(i,document)
# i:index,document:element
for i,_ in enumerate(documents):
do_something(i,documents)
# only index
压缩与参数拆分
如果想要把两个或者多个list压缩在一起,可以使用zip同时把多个list转换为一个对应元素的tuple 的single list:
list1 = [1,2,3]
list2 = ['a','b']
list=zip(list1,list2)
print(tuple(list))
list1 = [1,2,3]
list2 = ['a','b']
list3 = [4,5,6]
list=zip(list1,list2,list3)
print(tuple(list))
if the length of these lists aren’t same, zip will end at the shortest list
(最短截止)
解压
pairs = [(1,2),(3,4),(5,6)]
letters,numbers= zip(*pairs)
print(letters,numbers)
*(星号)执行参数拆分argument unpacking
⚠️可以在任何函数上进行参数拆分
def add(a,b):
return a+b
ans = add(1,2)
print(ans)
ans = add(*[1,2])
print(ans)
args 和 kwargs
如果想要创建一个更高阶的函数,把某个函数f作为input,并返回一个对任意输入都返回f值两倍的函数:
def doubler(f):
def g(x):
return 2*f(x)
return g
def f2(x,y):
return x+y
g = doubler(f2(1,2))
print(g(1,2))
对于有多个参数的函数就不适用
需要一个可以取任意参数的函数的method,利用参数拆分可以做到:
def magic(*args,**kwargs):
print("unnamed args:",args)
print("keyword args:",kwargs)
magic(1,2,key='word',key2='word2')
输出的未命名的args和关键字kwargs如下:
也就是说当定义了这样一个function时,args是它的一个未命名参数的tuple,kwargs是它的一个已命名参数的dict
反过来也适用,可以使用一个list/tuple和dict来给函数提供参数
def other_way_magic(x,y,z):
return x+y+z
x_y_list = [1,2]
z_dict = {"z":3}
print(other_way_magic(*x_y_list,**z_dict))
用它可以将任意参数作为输入的高阶函数
def doubler_correct(f):
def g(*args,**kwargs):
return 2*f(*args,**kwargs)
return g
def f2(x,y):
return x+y
g = doubler_correct(f2)
print(g(1,2))
因为传入函数的参数具有不确定性,所以像最开始那样直接固定参数个数不行,所以才用这种参数随便的method。