定义
迭代器是一个可以记住遍历位置的对象,从第一个元素开始访问,知道所有元素被访问结束,迭代器只能向后遍历,不能后退
一个实现了__iter__
方法和__next__
方法的对象就是迭代器
可迭代对象
只要能通过for…in…进行遍历的,那么这个数据类型就是可迭代对象
一个实现了__iter__
方法的对象就是可迭代对象
注意
迭代器一定是可迭代对象,可迭代对象不一定是迭代器
判断迭代器和可迭代对象
通过Iterable来判断是否是可迭代对象
from collections.abc import Iterable
a = []
print(isinstance(a, Iterable))
# True
通过Iterator来判断是否是迭代器
from collections import Iterator
t = []
print(isinstance(t,Iterator))
# False
t1 = iter(t)
print(isinstance(t1,Iterator))
# True
定义
在Python中,一边循环一边计算的机制称为生成器(生成器是一种特殊的迭代器)
创建生成器的两种方式
1.将列表推导式的[]换成()
[x for x in range(10)] ----> (x for x in range(10))
2.函数中含有yield关键字
def num():
num1 = 1
num2 = 2
while True:
temp_num = num1
num1, num2 = num2, num1 + num2
yield temp_num
n = num()
print(next(n))
print(next(n))
print(next(n))
print(next(n))
print(next(n))
-------------执行结果--------------
1
2
3
5
8
生成器的调用方法
next():唤醒函数,从断点处继续执行
send():唤醒函数,并向断点处传入一个值并继续执行
生成器的特点(优势)
生成器存储的是生成数据的方式,并不是存储数据,因此节约内存
定义
在函数内嵌套了另一个函数,内部函数用到了外部函数的局部变量,并且外部函数返回了内部函数的引用
def out_func(out_num):
def in_func(in_num):
return out_num + in_num
return in_func
ret = out_func(10)
ret(20) # 30
闭包和普通函数的区别
普通函数执行结束后会被python解释器自动释放局部变量,闭包可以让参数和变量不被垃圾回收机制回收,始终保存在内存中
定义
能够快速将函数的指向修改, 在不修改代码的前提下,给函数添加功能的方式
实现过程
将原函数的引用当做实参传递到闭包中;修改原函数的指向为闭包中的内部函数
**修饰无参函数
from time import ctime, sleep
# 定义一个闭包
def timefun(func):
def wrapped_func():
print("%s called at %s" % (func.__name__, ctime()))
func()
return wrapped_func
@timefun # 使用装饰器对foo进行装饰,此时相当于foo = timefun(foo)
def foo():
print("I am foo")
foo() # 相当于调用的是wrapped_func函数
sleep(2)
foo() # 相当于调用的是wrapped_func函数
修饰有参函数
from time import ctime, sleep
def timefun(func):
def wrapped_func(a, b):
print("%s called at %s" % (func.__name__, ctime()))
print(a, b)
func(a, b)
return wrapped_func
@timefun
def foo(a, b):
print(a+b)
foo(3,5)
sleep(2)
foo(2,4)
修饰不定长参数的函数
from time import ctime, sleep
def timefun(func):
def wrapped_func(*args, **kwargs):
# args=(3,5,7)
# kwargs = {}
print("%s called at %s"%(func.__name__, ctime()))
func(*args, **kwargs) # 对args,kwargs进行拆包,此时相当于func(3,5,7)
return wrapped_func
@timefun
def foo(a, b, c):
# a=3,b=5,c=7
print(a+b+c) # 15
foo(3,5,7) # 将3,5,7这些未命名参数传递到第5行函数中,此时args用元组存储
多个装饰器装饰同一个函数
# 定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "" + fn() + ""
return wrapped
# 定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "" + fn() + ""
return wrapped
@makeBold
def test1():
return "hello world-1"
@makeItalic
def test2():
return "hello world-2"
@makeBold
@makeItalic
def test3():
return "hello world-3"
print(test1())
print(test2())
print(test3())
带参数的装饰器
import time
def call_out2(timeout=0):
def call_out1(func):
def call():
print("----1----")
time.sleep(timeout)
ret = func()
print("----2----")
return ret
return call
return call_out1
# 下面的装饰过程
# 1. 调用timefun_arg("itcast") 得到一个返回值,即time_fun
# 3. 然后执行time_fun(foo) 得到一个返回值,即wrapped_func
# 4. 让foo = wrapped_fun,即foo现在指向wrapped_func
@call_out2(2)
def print_hello():
print("hello world")
return "ok"
print(print_hello())
使用类装饰
class Test(object):
def __init__(self, func):
print("---初始化---")
print("func name is %s" % func.__name__)
self.__func = func
def __call__(self):
print("---装饰器中的功能---")
self.__func()
#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
# 并且会把test这个函数名当做参数传递到__init__方法中
# 即在__init__方法中的属性__func指向了test指向的函数
#2. test指向了用Test创建出来的实例对象
#3. 当在使用test()进行调用时,就相当于直接调用实例对象,因此会调用这个对象的__call__方法
#4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
# 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
@Test
def test():
print("----test---")
test() # 如果把这句话注释,重新运行程序,依然会看到"--初始化--"