欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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("不管是否有异常, 都会执行的内容")

 

相关标签: 运维开发