迭代器
迭代器定义
- 拥有 _ iter _方法和 _ next _ 方法的对象就是迭代器
- 迭代
- 迭代是访问集合元素的一种方式,可以将某个数据集内的数据‘一个挨着一个的取出来’,就叫做迭代。
- 可迭代协议
- 协议就是互相规定好的。可迭代协议的定义非常简单,就是内部实现了_ iter _方法和 _ next _ 方法。
- 迭代器协议
- 必须拥有_ iter _方法和 _ next _ 方法
- 下面用迭代器生成一个斐波那契数列,代码示例如下:
class Fib():
def __init__(self,num):
self.num = num
self.a = 1
self.b = 1
self.count = 1
def __iter__(self):
return self
def __next__(self):
if self.count <= self.num:
temp = self.a
self.a,self.b = self.b,self.a+self.b
self.count+=1
return temp
else:
raise StopIteration
print(Fib(10))
for x in Fib(10):
print(x)
- 迭代器作用
- 节约内存,在取的时候再生成数据
生成器
- 生成器的本质就是迭代器
- 生成器包括两种:生成器函数和生成器表达式
生成器函数
- 一个包含yield关键字的函数就是一个生成器函数,并且yield和return不能共用,并且yield只能用在函数内。
- 生成器函数执行了之后会得到一个生成器作为返回值,并不会执行函数体。
- 执行了 __ next __ ()方法之后才会执行函数体,并且获得返回值。
- .next()内置方法,内部调用生成器函数的__ next __()方法。
- .yield和return相同的是可以返回值,但不同的是yield不会结束函数
示例代码如下:
def shengchan(n):
i = 1
while i <= n:
yield i
i += 1
x = shengchan(5)
print(x)
for i in x:
print(i)
输出结果如下:
<generator object shengchan at 0x0000000005347A40>
1
2
3
4
5
send()
- send获取下一个值的效果和next()基本一致,只是在获取下一个值的时候,给上一个yield的位置传递一个数据
- 使用send的注意事项
- 第一次使用生成器的时候,是用next获取下一个值
- 最后一个yield不能接受外部的值
示例代码如下:
def g():
count = 1
get_num = 0
avg = 0
total = 0
while True:
get_num = yield avg
total = total + get_num
avg = total/count
count+=1
x = g()
next(x)
print(x.send(10))
print(x.send(20))
print(x.send(30))
输出结果如下:
10.0
15.0
20.0
yield from
- yield from循环遍历容器类型
示例代码:
def g():
yield from 'AB'
yield from range(5)
for x in g():
print(x)
输出结果如下:
A
B
0
1
2
3
4
生成器表达式
- 格式:将列表解析式的 [ ]改成 ()即可。
示例代码如下:
a = ('鸡蛋%d'%i for i in range(1,11))
print(a)
print(next(a))
print(a.__next__())
print(list(a))
输出结果如下:
<generator object <genexpr> at 0x0000000005966938>
鸡蛋1
鸡蛋2
['鸡蛋3', '鸡蛋4', '鸡蛋5', '鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9', '鸡蛋10']
装饰器
闭包
- 在python中创建一个闭包一般有3个要求:
- 1.闭包函数必须有内嵌函数
- 2.内嵌函数必须要引用外层函数的变量
- 3.闭包函数返回内嵌函数的地址(函数名称)
装饰器
- 装饰器函数的本质:一个闭包函数
- 装饰器函数的作用:在不修改原函数及其调用方式的情况下对原函数功能进行扩展
- 语法糖:
- 格式: @装饰器名称
示例代码如下:
- 格式: @装饰器名称
import time
def decor(f):
def neibu():
t1 = time.time()
f()
t2 = time.time()
print('运行时间为:',(t2-t1))
return neibu
@decor
def func():
s = 1
for i in range(1,9):
s*=i
print(s)
func()
检测程序运行时间,结果如下:
40320
运行时间为: 0.0010001659393310547
多个装饰器的话,会先执行离得近的装饰器
def zsq(f):
def nb():
print('************************')
f()
print('************************')
return nb
def zsq2(f):
def nb():
print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
f()
print('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@')
return nb
@zsq2
@zsq
def f1():
print('欢迎领导')
@zsq
def f2():
print('好走,不送!')
f1()
print()
f2()
结果如下:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
************************
欢迎领导
************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
************************
好走,不送!
************************
还可以创建带返回值的装饰器,示例如下:
def acor(f):
def neibu(a,b):
print('***********')
d =f(a,b)
print('***********')
return d
return neibu
@acor
def func(a,b):
c = a+b
return c
print(func(2,3))
输出结果如下:
***********
***********
5
- @property 装饰器
- @property内置装饰器函数,把一个方法调用方式变成属性调用方式(将一个方法当成一个属性使用)。注意@property装饰器只能在面向对象中使用。
- 访问使用@property装饰器装饰的函数可以直接调用函数名
- @property装饰器只能修饰不带参数的方法
- @property装饰器修饰私有方法的getter和setter方法。
示例代码如下:
from math import pi
class Circle():
def __init__(self,r):
self.r = r
@property
def zhouchang(self):
return self.r*2*pi
@property
def area(self):
return pi*self.r**2
c = Circle(5)
print(c.zhouchang)
print(c.area)