生成器:
在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晓码阁 版权所有