python三大_Python之三大器

本文详细介绍了Python中的装饰器和迭代器。首先讲解了装饰器的概念,包括闭包和装饰器的作用,展示了如何使用装饰器来追踪函数执行时间。接着讨论了迭代器,解释了迭代器的定义和优点,以及for循环的工作原理。最后,介绍了生成器,它是自定义迭代器的一种实现方式,并通过yield关键字展示了如何创建和使用生成器。
摘要由CSDN通过智能技术生成

一、装饰器

闭包函数

闭:指的是定义在函数内部的函数

比如手机是闭包函数(内层函数),被手机包装盒 (外层函数) 包裹起来,

手机可以使用包装盒中的东西,内层函数可以引用外层函数的名字。

闭包函数:定义在函数内部的函数,并且该函数包含对外部函数作用域中名字的引用,该函数就称为闭包函数。

闭包函数是 函数嵌套、函数对象、名称空间与作用域 结合体。

基本形式:

def outer():

name ='egon'

def inner():

print('my name is %s' %name)

return inner

# print(outer())

inner=outer() #实现了外部调用内部的函数

inner()

注意:作用域关系在函数定义阶段就定死了,与调用位置无关

闭包函数外面最多套两层函数就够了

装饰器简介

器:工具

装饰:为被装饰对象添加新功能

装饰器:装饰的工具

被装饰对象--->>需要添加功能 的函数

装饰器--->>函数

装饰器的作用:在不修改被装饰对象源代码与调用方式的前提下,为其加上新的功能

装饰器必须要遵循的原则:开放封闭原则

为什么要使用装饰器:可以解决代码冗余问题,提高代码的可扩展性

开放封闭原则

开放:对函数功能的添加是开放的。

封闭:对函数功能修改是封闭的。

总结原则如下:

不修改被装饰对象源代码

不修改被修饰对象调用方式

目的:在遵循1和2原则的基础上扩展新功能

模拟下载电影函数的运行时间

import time

def download_m():

print('开始下载电影....')

time.sleep(3)

print('电影下载完成....')

#

# start_time = time.time()

# download_m()

# end_time = time.time()

# print(f'消耗时间:{end_time-start_time}')

def time_record():

def inner():

start_time = time.time() #统计开始

download_m() #写死了,只能给download_m函数用

end_time = time.time()

print(f'消耗时间:{end_time-start_time}') #结束统计,打印消耗时间

return inner

func = time_record() #返回的是inner的内存地址

func() #调用的实质其实是inner函数

改进版

import time

def download_m():

print('开始下载电影....')

time.sleep(3)

print('电影下载完成....')

# 添加时间功能

def time_record(func): # func = download_m

def inner():

start_time = time.time() #统计开始

# download_m() #写死了,只能给download_m函数用

func() # func() = download_m()

end_time = time.time()

print(f'消耗时间:{end_time-start_time}') #结束统计,打印消耗时间

return inner #返回的是inner的内存地址

res = time_record(download_m) #被装饰对象的调用方式

res()

问题1:被装饰对象,有返回值

def download_m():

print('开始下载电影....')

time.sleep(3)

print('电影下载完成....')

return "小丑.mp4"

def time_record(func):

def inner():

start_time = time.time()

res = func() # func() = download_m()

end_time = time.time()

print(f'消耗时间:{end_time-start_time}')

return res #res = download_m()

return inner

download_m = time_record(download_m) # time_record(download_m)=inner#重新赋值给download_m

download_m()

问题2:被装饰对象,有参数

def download_m(url):

print(f'{url}开始下载电影....')

time.sleep(3)

print('电影下载完成....')

return"小泽.mp4"

def time_record(func): # func

# url = 'https://www.baidu.com/'

# 在闭包函数中

def inner(url):

start_time = time.time()

res = func(url) # func(url) ---> download_movie(url)

end_time = time.time()

print(f'消耗时间: {end_time - start_time}')

return res

return inner

download_m = time_record(download_m)

download_m('https://www.baidu.com')

问题3: 假如被装饰对象需要接收多个参数

def download_movie(url1,url2):

print(f'{url1,url2}开始下载电影....')

time.sleep(3) # 等待3秒

print('电影下载成功...')

return '小泽.mp4'

#装饰器最终版本

def time_record(func):

def inner(*args,**kwargs): #*args,**kwargs接受所有的参数

start_time = time.time()

res = func(*args,**kwargs) # 将被装饰对象需要接收的任意参数 原封不动传给func

end_time = time.time()

print(f'消耗时间: {end_time - start_time}')

return res

return inner

download_movie = time_record(download_movie)

download_movie(url1='https://www.baidu.com', url2='https://www.hao123.com')

叠加装饰器

叠加装饰器:

在同一个被装饰对象中,添加多个装饰器,并执行。

@装饰1

@装饰2

@装饰3

def 被装饰对象():

pass

注意: 装饰器在调用被装饰对象时才会执行添加的功能。

- 叠加装饰器:

- 装饰的顺序: 由下到上装饰

- 执行的顺序: 由上往下

注意: 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象” func(*args, **kwargs)

无参装饰器: 装饰在被装饰对象时,没有传参数的装饰器。

有参装饰器: 本质上就是在无参装饰器上套了一个外层函数,无参装饰器可以引用外层函数的名字。

装饰器模板

def wrapper(func):

def inner(*args, **kwargs):

为被装饰对象添加新功能

res = func(*args, **kwargs) # 调用被装饰对象,得到返回值

为被装饰对象添加新功能

return res

return inner

def func1():

pass

func1 = wrapper(func1)

func1() # inner()

装饰器的语法糖

装饰器语法糖,是属于装饰器的。

@:装饰器的的语法糖

注意: 在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上。

import time

# 统计函数执行时间装饰器

def wrapper(func): # 被装饰对象

def inner(*args, **kwargs): # 被装饰对象的参数

start_time = time.time() # 调用前增加新功能

res = func(*args, **kwargs) # 调用被装饰对象,并接收返回值

end_time = time.time() # 调用后添加新功能

print(end_time - start_time)

return res

return inner

@wrapper # download= wrapper(download_m)

def download_m()

print('开始下载电影....')

time.sleep(3)

print('电影下载完成....')

download_m()

二、迭代器

定义:迭代取值的工具, 它可以迭代取值。

迭代:是指重复迭代,每一次迭代的结果都是基于上一次的结果而来的

-可迭代对象:所有序列类型:list、tuple、dict、str、set、f(文件)

#依赖于索引取值

goods=['mac','lenovo','acer','dell','sony']

index=0

while index < len(goods):

print(goods[index])

index+=1

dict1 = {'name':'bob','age':18,'sex':'male'}

iter_dict1 = dict1.__iter__() #iter_dict1是一个迭代器对象

print(iter_dict1.__next__())

print(iter_dict1.__next__())

print(iter_dict1.__next__())

>>>name

>>>age

>>>male

补充:

list1 = ['tank', 'jason鸡哥', 'sean', '饼哥']

iter_list1 = list.__iter__()

while True:

# 补充: try:获取异常

try:

print(iter_list1 = list.__iter__()) #报错

#立即触发此代码 StopIteration

except StopIteration

break

凡是内部有.__iter__()方法的都是可迭代对象。

例如:

str='hello'

str1.__iter__()

-获取迭代器:

通过可迭代对象.__iter__(),得到的返回值就是"迭代器对象

-如何迭代取值:

迭代器对象.__next__(),每次执行,都会从迭代器对象中取出一个值

-迭代器对象的优点:

1. 不依赖于索引迭代取值

2. 节省内存空间。

缺点:

1.取指定某个值麻烦

2.每次取值都要从第一个值开始,无法同过索引取值

3.无法通过len()计算长度

- 迭代器本质上是一个可迭代对象

- 文件本质上既是迭代器对象,也是可迭代对象。

- 可迭代对象不一定是迭代器对象

for循环原理:

for i in 可迭代对象:

- in: 会将可迭代对象自动调用.__iter__()变成迭代器对象

- for循环内置捕获异常机制

set1 = '1, 2, 3, 4'

iter_set1 = set1.__iter__() #iter_set1 迭代器

print(iter_set1.__iter__() is iter_set1) #True

list1 = [1, 2, 3, 4]

iter_list1 = list1.__iter__()

print(iter_list1 is list1) #False

三、生成器

什么是生成器?

生成的工具

生成器是一个“自定义”的迭代器,本质上就是一个迭代器

如何实现生成器

但凡在函数内部包含关键字yield,调用函数时,函数体代码不会执行,但会返回一个结果,该结果就是一个生成器

-yield:

只能在函数内部定义

每次yield都会往生成器对象中添加一个值,

yield可以保存函数的暂停状态

yield与return:

相同点:

返回值的个数都是无限制的。

不同点:

return只能返回一次值,yield可以返回多次值

# 自定义的迭代器:

def func():

print('form func')

yield 1

res = func() #res是一个生成器

print(res) #

#当我们通过.__next__取值时,才会执行函数体代码。

def func():

print('from func')

yield 1

res = func()

print(res.__next__())

def func():

print('开始准备下蛋')

print('一个鸡蛋')

yield '鸡蛋1'

print('第二个鸡蛋')

yield '鸡蛋2'

print('第三个鸡蛋')

yield '鸡蛋3'

print('取最后一个鸡蛋,查看是否还有')

res = func() #res是迭代器对象

# print(next(res))

# print(next(res))

# print(next(res))

# print(next(res)) #StopIteration 报错

迭代器对象.__next__() ==next(迭代器对象)

print(res.__next__()) #当我们通过.__next__取值时,才会执行函数体代码

print(res.__next__())

print(res.__next__())

print(res.__next__()) #StopIteration 报错

# 循环10次

for i in range(1,11):

print(i)

# python2:range(1,5)--->[1,2,3,4]

# python3:range(1,5) --->range对象 --->生成器 --->迭代器

#自定义range功能,创建一个自定义的生成器

def my_range(start,end,move):

while start

yield start

start +=move

g_range = my_range(1,5,2) #g_range 是生成器

print(g_range)

原文:https://www.cnblogs.com/baohanblog/p/12143040.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值