生成式、装饰器、高阶函数
一、生成式
(1)、列表生成式
列表生成式就是一个用来生成列表的特定语法形式的表达式。是Python提供的一种生成列表的简洁形式,可快速生成一个新的list。
1、使用方法
普通的语法格式:[exp for iter_var in iterable]
带过滤功能语法格式: [exp for iter_var in iterable if_exp]
带过滤功能语法格式: [exp for iter_var in iterable if_exp]
2、基本运用
它可以将繁琐的方法1简化为方法2
方法1
import string
import random
codes = []
for count in range (100): #循环100次,每次都任意生成4个字符串
code = "".join(random.sample(string.ascii_letters,4))
codes.append(code)
print(codes)
#结果
['MIFp', 'zJct', 'KpNB', 'afcS', 'zCnv', 'nzgH', 'IlhR', 'UHJk', ....
方法2
codes = [ "".join(random.sample(string.ascii_letters,4)) for i in range(100)]
print(codes)
#结果
['mnLM', 'LVKe', 'ntlM', 'BjYl', 'KIAt', 'gRBl', 'QiqH', ...
3、练习题
找出1到100里面可以被3整除的数
方法1
nums = []
for num in range(1,100):
if num % 3 == 0:
nums.append(num)
print(nums)
方法2
利用公式生成器
nums = [num for num in range(1,100) if num % 3 == 0]
print(nums)
(2)、集合生成式
集合生成公式如下
result = {i**2 for i in range(10)}
print(result)
#结果
{0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
(3)、字典生成式
字典生成式如下
result={i:i**2 for i in range(10)}
print(result)
#结果
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
二、生成器
(1)、生成器特点
在python中一边循环一边计算的机制叫做生成器
运用场景
(2)、使用方法
1、生成器的方法
方法1:实现的第一种方法(将生成式改写为生成器即可)
nums = (i**2 for i in range(1000))
print(nums)
#结果
<generator object <genexpr> at 0x0000018FFF234900>
上面的不太方便查看,可以用下面这种方法查看值
nums = (i**2 for i in range(1000))
for num in nums:
print(num)
#结果
0
1
4
9
16
25
36
。。。
方法2:yield关键字
return:函数遇到return就返回,后面的函数不会执行。
yield: 遇到yield则停止执行代码,再次调用next方法时,从上次停止的yiled继续执行到下一个yield
def login():
print('step1') # step
yield 1 #output
print('step')
yield 2
print('step 3')
yield 3
# 如果函数里面有yield关键字,说明函数的返还值是一个生成器
g = login()
print(next(g))
print(next(g))
三、闭包
(1)、了解时间戳
import time
start_time=time.time() #从1970.1.1到现在的秒数
time.sleep(2) #休眠两秒
end_time = time.time() #从1970.1.1到现在的秒数
print(end_time-start_time)
#结果
2.00744891166687
(2)、闭包
1、函数里面嵌套函数
2、外部函数的返回值是内部函数的引用
3、内部函数可以使用外部函数的变量
import time
def timeit(name):
def wrapper():
print('wrapper'+name)
print('timeit')
return wrapper
in_fun = timeit(name = 'westos') in_fun此时相当于wrapper函数
in_fun() 相当于同时调用了内部和外部的函数
四、装饰器
(1)、装饰器
1、基本模板
import time
from functools import wraps
def 装饰器名称(f):
@wraps(f) 保留被装饰器函数的帮助文档
def wrapper(*args,**kwargs):
#这里可以添加执行函数前的事情
result=f(*args,**kargs)
#执行函数之后做的事情
return result 返还函数给被装饰的函数
return wrapper()
2、举例
# 装饰器:用于装饰函数的功能
# 在不改变源代码的情况下,去添加额外功能的工具
# 用闭包实现装饰器
import time
def timeit(f):
def wrapper(x,y):
start = time.time()
result= f(x,y) #执行的是add(x,y)
end = time.time()
print('函数运行的时间为:%.4f'%(end-start))
return result
return wrapper
@timeit #装饰糖,这里时间上是将add函数转换为timeit(add())
def add(x,y):
return x+y
result = add(1,3)
print(result)
3、添加wraps,可以对函数的帮助文档进行分别说明
# 装饰器:用于装饰函数的功能
# 在不改变源代码的情况下,去添加额外功能的工具
# 用闭包实现装饰器
import time
from functools import wraps
def timeit(f):
"""" 计时器的装饰器 """
@wraps(f) #保留被装饰函数的属性信息和帮助文档
def wrapper(*args,**kwargs):
start = time.time()
result= f() #执行的是login()
end = time.time()
print('函数运行的时间为:%.4f'%(end-start))
return result
return wrapper
@timeit #装饰糖,这里时间上是将add函数转换为timeit(add())
def login():
""""login的帮助文档"""
print('login')
print(help(timeit))
(2)、含参数的装饰器
import time
from functools import wraps
def timeit(args='seconds'):
def desc(f):
"""" 计时器的装饰器 """
@wraps(f) 保留被装饰函数的属性信息和帮助文档
def wrapper(*args,**kwargs):
start = time.time()
result= f() 执行的是login()
end = time.time()
if args =='seconds':
print(f"函数{f.__name__}运行的时间为{end-start}秒")
elif args == 'mintues':
print(f"函数{f.__name__}运行的时间为{(end - start)/60}秒")
return result
return wrapper
return desc
@timeit(args='mintues') 先实现timeit() 它将@执行desc函数,即desc=desc(login)
def login():
""""login的帮助文档"""
print('login')
login()
(3)、多个装饰器
注意修饰器的调用顺序是从下到上,先调用第二个装饰器is_permisson,再调用第一个装饰器 is_login,但是最终的结果是从上到下 ,输出一个装饰器的结果,再输出第二个装饰器的结果,最终再执行函数的结果。
from functools import wraps
def is_login(f):
@wraps(f)
def wrapper1(*args,**kwargs):
print('is_login,用户是否登录')
result=f(*args,**kwargs)
return result
return wrapper1
def is_permisson(f):
@wraps(f)
def wrapper2(*args,**kwargs):
print('is_permission,用户是否拥有权限')
result=f(*args,**kwargs)
return result
return wrapper2
@is_login
@is_permisson 注意修饰器的调用顺序是从下到上,先调用is_permisson,再调用 is_login
def show_hosts():
print('显示所有的云主机')
show_hosts()
具体调用顺序如下
1、is_permisson模块先调用
先show_host=is_permisson(show_hosts)
得到结果show_host=wrapper2
2、is_login模块再被调用
show_hosts = is_login(wrapper2) (因为上一个装饰器使得show_hosts为wrapper2,因此这里传入的函数为wrapper2)
得到结果show_hosts=wrapper1
3、上面两步装饰完毕,进行第三步执行show_hosts函数。
现在show_hosts的函数时wrapper1,因此执行show_hosts函数实际是执行wrapper1函数,输出为:
’is_login,用户是否登录‘
然后执行f(*args,**kwargs),根据步骤2发现传进来的函数是wrapper2,因此执行wrapper2函数,输出为:
‘is_permission,用户是否拥有权限’
最后执行执行f(*args,**kwargs),根据步骤1发现传进来的函数是show_hosts,因此执行show_hosts本身函数,输出为:
‘显示所有的云主机’
五、内置高阶函数
(1)、map函数
同时并行的进行处理
#计算x的2次方
result = map(lambda x:x**2,[1,2,3,4])
print(list(result))
#结果
[1, 4, 9, 16]
result=map(lambda x,y:x+y,[1,2,3],[4,5,6])
print(list(result))
#结果
[5, 7, 9]
(2)、reduce函数
将前者的结果作为后者的输入
# reduce函数
# 计算((2**3)**3)=reduce result
from functools import reduce
result = reduce(lambda x, y: x**y, [2, 3, 3])
print(result)
练习·:计算1×2×。。。100
from functools import reduce
result = reduce(lambda x,y: x * y,list(range(1,100))) 注意一定要转换为列表
print(result)
(3)、filter函数
筛选函数
筛选出偶数
result=filter(lambda x:x % 2==0,[1,2,4,5])
print(list(result))
#结果
# filter函数
result=filter(lambda x:x % 2==0,[1,2,4,5])
print(list(result)) 输出为列表
(4)、sorted函数
进行数字大小排序,从小到大
result = sorted([1,4,321,2])
print(result)
result = sorted([1,4,321,2],reverse=True)
print(result)
#结果
[321, 4, 2, 1]
根据数字是否为0进行排序
函数里面的规则是将非01的赋予为1,然后根据 0 ,1进行排序,根据排序后进行返还真实值
result = sorted([1,4,0,2],key=lambda x:0 if x==0 else 1)
print(result)
[0, 1, 4, 2]