Linux自动化运维——Python(7)(简单理解Python中的生成式,生成器,闭包,装饰器)
程序员文章站
2022-03-04 12:59:03
...
1.生成式
(1)列表生成式
列表生成式就是一个用来生成列表的特定语法形式的表达式。是Python提供的一种生成列表的简洁形式, 可快速生成一个新的list。
• 普通的语法格式:[exp for iter_var in iterable]
• 带过滤功能语法格式: [exp for iter_var in iterable if_exp]
• 循环嵌套语法格式: [exp for iter_var_A in iterable_A for iter_var_B in iterable_B]
代码实现
# 1. 生成式: 用来快速生成某一个数据类型的式子.
# 列表生成式[],集合生成式{},字典生成式{}
# 需求: 已知: x=1..10, 求y=2x+8,并将求出的所有y值存储到列表中
# 需求提升: x=2, 4, 6, 8,10, 求y
"""
# Method 1:
result = []
for x in range(1, 11):
y = 2*x+8
result.append(y)
# print(y)
print(result)
"""
result = [ 2*x+8 for x in range(1, 11) ]
print(result)
# 列表生成式中for循环里面可以嵌套if语句,也可以嵌套for语句.
# 如何判断一个数是偶数? x%2==0?偶数:奇数
result = [ 2*x+8 for x in range(1, 11) if x%2==0 ]
(2)集合生成式:用来快速生成集合;
# 什么场景使用/改写成生成式?
"""
li = []
for x in 序列:
y = 对x做了操作
需要把y存储起来,
"""
# 集合生成式
result = {x**2 for x in range(1, 11)}
print(result)
print(type(result))
(3)字典生成式:用来快速生成字典
# 字典生成式
# key:value
result = {key:key**2 for key in range(10)}
print(result)
print(type(result))
2.生成器
(1)定义:在Python中,一边循环一边计算的机制,称为生成器:Generator。
(2)创建与调用
• 如何创建生成器?
第一种方法: 列表生成式的改写。 []改成()
第二种方法: yield关键字。
• 如何打印生成器的每一个元素呢?
通过for循环, 依次计算并生成每一个元素。
如果要一个一个打印出来,可以通过next()函数获得生成器的下一个返回值。
# 生成器:
# 1. 什么是生成器?
# 2. 生成器应用在什么场景?有什么优势?
# 3. 如何创建生成器? 1). 生成式改写 2).yield关键字
# 1). 创建生成器的方法1:生成式改写
# g就是生成器对象, 一边循环一边计算, 你需要的时候他才帮你计算(next(g))
# 怎么让生成器进行计算? 1). next(g) 2). 通过for循环遍历生成器对象
"""
g = (x**2 for x in range(10))
for item in g:
print(item)
"""
# 2). 创建生成器的方法2:yield关键字
"""
# 理解return关键字的工作原理
def welcome():
while True:
print('step 1')
# 函数中遇到return,函数执行结束,后面的代码不会继续执行
return 'ok'
print('step 2')
result = welcome()
print(result)
"""
# yield(停靠,让步)
# 函数中遇到yield关键字,函数执行停止,知道调用下一个next函数,从停止的地方继续执行。
def welcome():
count = 1
while count <= 10:
print('step %d' %(count))
count += 1
# 函数中遇到return,函数执行结束,后面的代码不会继续执行
yield 'ok'
# 如果函数中包含yield关键字,调用函数的返回值是生成器,这个时候函数并没有执行.
g = welcome()
# 通过调用next函数才开始执行函数的内容,遇到yield就停止执行.
print(next(g))
# 当再次调用next方法时, 从上次停止的地方继续执行,直到遇到yield关键字停止
print(next(g))
print(next(g))
for x in g:
print(x)
3.闭包
什么是闭包?如何实现闭包?
闭包就是指有权访问另一个函数作用域中的变量的函数。创建闭包最常见方式,就是在一个函数内部创建另一个函数
常见形式: 内部函数使用了外部函数的临时变量,且外部函数的返回值是内部函数的引用。
闭包的一个常用场景就是装饰器。
# 闭包需要满足的三个条件:
# 1). 函数里面嵌套函数
# 2). 内部函数使用外部函数的变量
# 3). 外部函数的返回值是内部函数的引用(函数名)
# ***强调: 定义函数不执行函数里面的代码,调用函数时才执行函数里面的代码。
def timeit(name):
# wrapper包装纸
def wrapper():
print(name)
return 'ok'
return wrapper
# 调用timeit函数,函数的返回值是wrapper函数引用,这里的result就是wrapper函数
result = timeit("westos")
# result目前是wrapper函数, result()就是在调用wrapper函数.
print(result())
4.装饰器
(1)以装饰器指的是为被装饰器,对象添加额外功能的工具/函数。装饰器本质上是一个函数
(2)为什么使用装饰器
如果我们已经上线了一个项目,我们需要修改某一个方法,但是我们不想修改方法的使用方法,这个时候可以使用装饰器。因为软件的维护应该遵循开放封闭原则,即软件一旦上线运行后,软件的维护对修改源代码是封闭的,对扩展功能指的是开放的。装饰器的实现必须遵循两大原则:封闭: 对已经实现的功能代码块封闭。 不修改被装饰对象的源代码• 开放: 对扩展开发
# 装饰器: 用来装饰函数或者类的工具, 在不改变源代码的情况下给函数/类添加额外功能.
# 装饰器装饰的是函数/类,所以需要传递的参数是函数名或者类名。
import time # 时间处理模块
# HTTP请求库,多用于网络爬虫, 需要pip install 下载的
import requests
# 1). 如何去创建装饰器?
# 需求: 添加功能-计算被装饰函数运行的时间的工具
def timeit(f):
"""
添加被装饰函数执行的时间
"""
# *args和**kwargs是形参还会实参?形参
# *args:可变参数, 可以接收多个参数信息,一般存储到元组中
# **kwargs:关键字参数,可以接收多个键值对信息,一般存储到字典中
# wrapper(10, 20) 接收时用元组来存储(10, 20)
def wrapper(*args, **kwargs):
# 函数执行之前计算当前的时间戳
start = time.time()
# 调用被装饰的函数,并保存函数的返回值
# *args和**kwargs是形参还是实参? 实参
# 注意: 这里不是可变参数的意思,是解包的意思.args=(10, 20) *args=10,20
# f(10, 20)==add(10,20)
result = f(*args, **kwargs)
# 函数执行之后计算当前的时间戳
end = time.time()
print("函数%s执行使用的时间是%.3fs" %(f.__name__, end-start))
return result
return wrapper
# 2. 如何去使用装饰器[email protected]装饰器的名称
# @timeit的工作原理: download_music=timeit(download_music)
# 执行的过程:
# 1). timeit(download_music)函数的返回值是wrapper函数名.
# 2). download_music=timeit(download_music), 让download_music=wrapper
# 3). 最后一行download_music(),实质上执行的函数wrapper()
# 4). 执行wrapper函数时, f()实质上执行的函数download_music()
@timeit
def download_music():
url = "http://m10.music.126.net/20200719111612/e36c0e235dbad219e9d8f0e65fa62007/ymusic/0201/7233/bea2/2cb43c8bcaa7797d32e5ca9b831350d8.mp3"
# 模拟浏览器访问mp3的网址,获取服务器端给我们的响应(response)
response = requests.get(url)
# 获取mp3音乐的内容
# music_content = response.content
# 打开文件,存储音乐的内容到文件中
with open("再见.mp3", 'wb') as f:
f.write(response.content)
print("再见.mp3下载完成.......")
@timeit
def add(num1, num2):
time.sleep(0.2)
return num1 + num2
# download_music()
"""
分析add函数执行的过程:
1. add(10, 20)调用函数
2. 发现add函数被装饰器timeit装饰了, @timeit==> add=timeit(add)
3. timeit(add)函数的返回值是wrapper函数, add=timeit(add)这里add=wrapper
4. 终于知道add函数是什么了.add(10, 20)===> wrapper(10, 20)
5. 在wrapper函数中有f()===> add(10, 20)
6. 返回f()函数的返回值30
"""
print(add(10, 20))
5.Python中的异常处理机制
try:
print("可能会出现异常的代码")
li = [1, 2, 3, 4]
print(li[9])
except IndexError as e:
print("出新索引异常")
print(li[-1])
else:
print("没有出现异常")
finally:
print("不管是否有异常, 都会执行的内容")