迭代器
拥有__iter__方法和__next__方法的对象就是迭代器
dir()方法获取对应数据类型的所有方法
dir()方法获取对应数据类型的所有方法,带有下划线的方法叫双下方法。
例如:print(dir( [ ]))
找到__iter__方法,有此方法的对象就是一个可以被迭代的对象。
__iter__方法的作用是返回一个迭代器
一个列表执行了__iter__()方法后返回值就是一个迭代器。
print([1,2,3].__iter__())
#<list_iterator object at 0x0000000002124400>
__iter__( )中 有一个__nexr__( )方法。这个方法可以迭代。
k=[1,2,3]
d=k.__iter__() #获取迭代器
print(d.__next__()) #获取1元素
print(d.__next__()) #2
print(d.__next__()) #3
(二)for循环原理
1.for循环一个可迭代的对象(实现__iter__方法)
2.__iter__方法返回一个迭代器(迭代器实现了__iter__方法和__next__方法)
3.for先判断对象方可迭代,然后调用迭代器的__next__方法获取值。
(三)迭代器的作用
节约内存,取值的时候再生成数据。
生成器
生成器的本质就是迭代器
生成器包括两种:生成器函数和生成器表达式
(一)生成器函数
一个包含yield关键字的函数就是一个生成器函数。并且yield不能和return共用,并且yield只能用在函数内。
1.生成器函数执行之后会得到一个生成器作为返回值,并不会执行函数体。
2.执行了__next__( )方法之后才会执行函数体,并且获得返回值。
3. .next() 内置方法,内部调用生成器函数的__next__()方法。
4. .yield和return相同的是可以返回值,但不同的是yield不会结束函数。
def shengcheng(n):
i=1
while i<=n:
yield i #yield返回值,并不会完全结束函数,而是保存下来当前的状态,
#等到下次进入的时候,继续使用
i+=1
x=shengcheng(5)
print(x)
for y in x:
print(y)
def dee():
yield 1
yield 2
yield 3
x=dee()
print(next(x))
print(next(x))
print(next(x))
(二)send()
send获取下一个值得效果和next()基本一致,只是在获取下一个值的时候,给上一个yield的位置传递一个数据
注意事项:
1第一次使用生成器时,是用next获取下一个值
2.最后一个yield不能接受外部的值。
def g():
print('a')
x=yield 10
print('接收数据',x)
yield x+5
x=g()
print(next(x))
b=x.send(999)
print(b)
#a
#10
#接收数据 999
#1004
例题计算移动平均值:
(三)yield form
yield from循环遍历容器类型
方式一:
def g():
yield from 'AB'
yield from range(5)
for x in g():
print(x)
#A b 0 1 2 3 4
方式二:
def g():
for x in 'AB':
yield x
for x in range(3):
yield x
for i in g():
print(i)
# A B 0 1 2
( 四)生成器表达式
格式:将列表解析式[ ]改成()即可
b=(i for i in range(5))#生成器表达式
print(b)
#<generator object <genexpr> at 0x00000000027545E8>
a=('鸡蛋%d'%i for i in range(1,6))
print(next(a)) #鸡蛋1
print(a.__next__()) #鸡蛋2
print(list(a)) #['鸡蛋3', '鸡蛋4', '鸡蛋5']
装饰器
闭包
在python中创建一个闭包有三个要求
1.闭包函数必须有内嵌函数。
2.内嵌函数必须要引用外层函数变量。
3.闭包函数返回内嵌函数的地址(函数名称)
def waiceng(b):
a=3
def neiceng(x):
return x*a+b
return neiceng
x=waiceng(9)
print(x(5))
print(x(7))
判断闭报的函数的方法__closure__
输出的__closure__有 cell 元素 是闭包函数
输出的__closure__为None 不是闭包函数
def waiceng():
b=9
def neiceng():
print('哈哈',b)
print(neiceng.__closure__)
return neiceng
x=waiceng()
x()
#(<cell at 0x0000000002771768: int object at 0x000007FED5FE6390>,)
#哈哈 9
装饰器
装饰器的本质:一个闭包函数
作用:在不修改原函数及其调用方式的情况下对原函数功能进行扩展。
import time
def decor(f):
def neibu():
#被装饰的函数之前执行的代码
t=time.time()
f() #被装饰的函数
#被装饰的函数之后执行的代码
t2=time.time()
print('时间{}'.format(t2-t))
return neibu
@decor
def func2():
s=0
for i in range(12771):
s+=1
print(s)
func2()
#12771
#时间0.0009999275207519531
(三)@property装饰器
1.@property内置装饰器函数,把每一个方法调用方式变成属性调用方式。(将一个方法当成属性使用)。@property装饰器只能在面向对象中使用。
2.访问使用@property装饰器装饰的函数可以直接调用函数名。(会执行一段功能(函数),然后返回值)
3.@property装饰器只能修饰不带参数的方法。
class A():
def __init__(self,name):
self.__name=name
@property
def name(self):
return self.name
# @name.setter #没有设置setter装饰器,不能设置name属性的值。
def name(self,x):
self.__name=x
a=A('张三')
print('张三')
a.name='李四'
print
#张三