生成器:
在Python中, 一边循环一边计算的机制, 称为生成器: generator
创建生成器: G = ( x*2 for x in range(5))
可以通过 next(生成器) 函数获得生成器的下一个返回值
没有更多的元素时, 抛出 StopIteration 的异常
生成器也可以使for 循环,因为生成器也是可迭代对象
创建生成器的方式:
1.
g = (列表推导式)
2.
Yield
列表推导式的代码体现形式
# list1 = [2,4,6,8...10] list1 = [] #循环操作 for i in range(2,101,2): list1.append(i) print(list1) #列表推导式 list2 = [x for x in range(2,101,2)] list3 = [x for x in range(101) if x % 2 == 0 if x != 0 if x >=50] print(list2) print(list3)
创建生成器
# 生成器的定义方式 g = (列表推导式) g = (x for x in range(101) if x % 2 == 0 if x != 0 if x >=50) print(type(g)) # print(g) print(next(g)) print(next(g)) print('-'*50) #使用for循环遍历生成器能生成的所有的数据 for v in g: print(v) print('-'*50) #超出生成器生成的范围“StopIteration”异常 # print(next(g)) # print(g.__next__()) print("yield关键字....................") def test(): for x in range(10): #加入yield关键字,函数调用变成生成器 yield x print("----") # print(x) g = test() # print(type(g)) #生成一个数据 # 输出0,程序在yield关键字停下 print(g.send(None)) # 输出(----,1),程序又在yield关键字停下 print(next(g)) # 输出(----,2),程序又在yield关键字停下 print(g.__next__()) # 输出(----,3),程序又在yield关键字停下 print(g.send(""))
必须清楚yield关键字参与后的方法执行顺序
生成器在线程中的使用
def save_money(): while True: print("存入¥1999") yield None def draw_money(): while True: print("取出Y1999") yield None g_save = save_money() g_draw = draw_money() while True: # save_money() # draw_money() g_save.__next__() g_draw.__next__()
迭代器:
迭代:
遍历的一种方式
可迭代性:iterable
如何判断一个对象是否具备可迭代性?
1.判断目标对象是否属于Iterable类 instance
2.for 循环
论证:
测试列表,字符串,元组,字典,生成器,是否具备可迭代性,
迭代器: Iterator
能够使用next()函数调用,并不断返回下一个值的对象,称为迭代器
生成器是否是迭代器? 是
列表、元组、字符串、字典是否是迭代器? 不是
结论:
1、具备可迭代性的不一定是迭代器
2、将具备可迭代性的对象转换为迭代器
iter(具备可迭代性的对象)
from collections.abc import Iterable,Iterator list1 = [x for x in range(10)] #测试列表是否具备可迭代性 if isinstance(list1,Iterable): for x in list1: print(x,end=' ') print() #字符串是否具备可迭代性 str1 = 'HelloWorld' if isinstance(str1,Iterable): for ch in str1: print(ch,end=" ") print() tuple1 = tuple(list1) #元组是否具备可迭代性 if isinstance(tuple1,Iterable): for x in tuple1: print(x,end=' ') print() #测试字典是否具备可迭代性 dict1 = {'one':1,'two':2,'three':3,'four':4,'five':5} if isinstance(dict1.values(),Iterable): for v in dict1.values(): print(v,end=" ") print() #测试生成器是否具备可迭代性 g = (x for x in range(10)) if isinstance(g,Iterable): for x in g: print(x,end=' ') print() #判断生成器是否为迭代器 if isinstance(g,Iterator): print("生成器就是迭代器") # next(g) if isinstance(list1,Iterator): print("列表是迭代器") else: print("列表不是迭代器") list1 = iter(list1) if isinstance(list1, Iterator): print("转换后的列表是迭代器") else: print("列表不是迭代器") print(next(list1)) all_items = dict1.items() print(type(all_items)) if isinstance(all_items,Iterable): for k,v in all_items: print(k,v) all_items = iter(all_items) print(type(all_items)) if isinstance(all_items,Iterator): print("是迭代器") else: print('No')
什么是闭包?
嵌套定义的函数,内部函数使用外部变量,内部函数就称为闭包。
如何定义一个闭包?
1.函数嵌套定义
2.内部函数使用外部函数作用域内的变量
3.外部函数必须有返回值,返回内部函数名
闭包的使用!
好处:
将外部函数中,局部变量的生命周期延长,程序周期
闭包代码体现形式的区别
# 普通函数定义方式 def test(num1,num2): print(num1+num2) test(10,20) #外部函数 def func_out(num1): #内部函数 闭包 def func_in(num2): return num1 + num2 return func_in func_in123 = func_out(10) print(type(func_in123)) result = func_in123(20) print(result) result1 = func_in123(100) print(result1) result2 = func_in123(30) print(result2) func_in = func_out(20) # result3 = func_in123(30) 40 result3 = func_in(30) print(result3)
闭包的应用
""" 用法: 求原点到指定点的距离 sqrt((x-x1)^2 + (y-y1)^2) 1.函数 2.闭包 """ import math #求两个点之间的距离 def get_dis(x,y,x1,y1): return math.sqrt((x-x1)**2 + ((y-y1)**2)) print(get_dis(0,0,3,4)) print(get_dis(0,0,30,40)) def get_dis_out(x,y): def get_dis_in(x1,y1): return math.sqrt((x - x1) ** 2 + ((y - y1) ** 2)) return get_dis_in #使用变量get_dis_in 存储get_dis_out(0,0) 的返回值(返回值为一个函数名) get_dis_in = get_dis_out(0,0) # print(get_dis_in(3,4)) print(get_dis_in(30,40))
结论:在某些业务开发的场景中可能需要利用到闭包,比如说游戏开发中的两点之间的距离计算,利用闭包可以简化代码的书写;
个人认为装饰器是闭包的一种体现形式。
我们用一个业务需求来说明装饰器在开发中的使用场景。
需求:
在已有的两个方法中添加日志功能
1. 记录事件 2.记录时间 3.写入日志文件
功能v1.0写法
import time def write_log(file_name,func_name): # 记录当前时间,记录访问方法,写入日志文件 try: file = open(file_name, 'a', encoding='utf-8') time_str = time.ctime() content = time_str + '\t' + func_name + '\n' file.write(content) except Exception as e: print(e) finally: file.close() def func1(): write_log('log.txt','func1') print("功能1") def func2(): # 记录当前时间,记录访问方法,写入日志文件 write_log('log.txt', 'func2') print("功能2") func1() func2()
功能v2.0写法(不改动原有代码)
""" 开发中的开闭原则: 开放: 添加功能开放 关闭: 修改源码 """ import time def write_log(file_name,func_name): # 记录当前时间,记录访问方法,写入日志文件 try: file = open(file_name, 'a', encoding='utf-8') time_str = time.ctime() func_name = func_name content = time_str + '\t' + func_name + '\n' file.write(content) except Exception as e: print(e) finally: file.close() def func1(): print("功能1") def func2(): print("功能2") #使用闭包完成功能的添加 def func_out(func,file_name): def func_in(): #新增功能(写入日志文件) write_log(file_name,func.__name__) #func是传进来的一个函数,调用函数 func() return func_in func1 = func_out(func1,'log.txt') func1() func2 = func_out(func2,'log.txt') func2()
功能v3.0写法import time
def write_log(file_name,func_name):
# 记录当前时间,记录访问方法,写入日志文件
try:
file = open(file_name, 'a', encoding='utf-8')
time_str = time.ctime()
func_name = func_name
content = time_str + '\t' + func_name + '\n'
file.write(content)
except Exception as e:
print(e)
finally:
file.close()
#使用闭包完成功能的添加
def func_out(func):
def func_in():
#新增功能(写入日志文件)
write_log('log.txt',func.__name__)
#func是传进来的一个函数,调用函数
func()
return func_in
#func1 = func_out(func1)
@func_out
def func1():
print("功能1")
#func2 = func_out(func2)
@func_out
def func2():
print("功能2")
# func1 = func_out(func1,'log.txt')
# func1()
# func2 = func_out(func2,'log.txt')
# func2()
func1()
func2()
上面这种方式,就是用装饰器替代了闭包的使用,从而简化了代码的书写,并且同时也没有改动原有的业务代码;
over......
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有