Python学习笔记(7)

9 迭代器、生成器与装饰器

9.1 迭代器

凡是使用for语句,本质上都迭代器的应用

9.1.1 迭代器概述

__iter__()  返回对象本身,for语句使用迭代器的要求
__next__()  用于返回容器中下一个元素或数据,必须加StopIteration引发异常

任何一个类,只要它实现了上述两个方法,就称为迭代器,就可以rof来遍历它
for item in iterator
    pass

9.1.2 自定义迭代器

In [4]:

class MyIterator:
    
    def __init__(self,x=2,xmax=100):
        self.__mul,self.__x=x,x
        self.__xmax=xmax
        
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.__x and self.__x !=1:
            self.__mul *= self.__x
            if self.__mul <= self.__xmax:
                return self.__mul
            else:
                raise StopIteration
        else:
            raise StopIteration
            
            
if __name__ == '__main__':
    myiter = MyIterator()
    for i in myiter:
        print('迭代的数据元素为:',i)
迭代的数据元素为: 4
迭代的数据元素为: 8
迭代的数据元素为: 16
迭代的数据元素为: 32
迭代的数据元素为: 64

9.1.3 内置迭代器工具

1、内建迭代器函数iter()
iter(iterable) iterable为可迭代的类型。
iter(callable,sentinel) callable可调用的类型,一般为函数;sentine称为‘哨兵’,即当第一个参数调用返回值等于第二个参数的值时,迭代或遍历停止。

In [14]:

class Counter:
    def __init__(self,x=0):
        self.x = x
        
counter = Counter()

def used_iter():
    counter.x += 2
    return counter.x

#print(used_iter())
for i in iter(used_iter,8):
    print('本次遍历的数值:',i)
本次遍历的数值: 2
本次遍历的数值: 4
本次遍历的数值: 6
2、itertools
无限迭代器:
count(start,[step])  从start开始,以step为步长
cycle(seq)  无限循环迭代seq
repeat(elem,[n])  循环迭代elem

迭代短序列:
chain(p,q,...)  链接迭代
compress(data,selectors)  依据selectors中的值选择迭代data序列中的值
filterfalse(pred,seq)  当pred处理为假的元素
dropwhile(pred,seq)  依据pred对序列元素处理为假时开始迭代seq后所有的值
takewhile(pred,seq)  与dropwhile向反
tee(it,n)  将it重复n次进行迭代
zip_logest(p,q,...) 

组合迭代序列:
product(p,q,...[,n])  迭代排列出所有的排列
permuations(p,r)  迭代序列中r个元素的排列
combinations(p,r)  迭代序列中r个元素的组合

In [28]:

import itertools
for i in itertools.count(1,3):
    print(i)
    if i >= 6:
        break
        
print('------------------------------------')
        
x = 0
for i in itertools.cycle(['a','b']):
    print(i)
    x += 1
    if x >= 6:
        break
        
print('------------------------------------')

print(list(itertools.repeat(3,3)))

print('------------------------------------')

print(list(itertools.chain([1,3],[2,3])))

print('------------------------------------')

print(list(itertools.dropwhile(lambda x:x>6,[8,9,1,2,8,9])))

print('------------------------------------')

print(list(itertools.takewhile(lambda x:x>10,[18,19,1,21,8,9])))

print('------------------------------------')

for its in itertools.tee([0,1],2):
    for it in its:
        print(it)
        
print('------------------------------------')

print(list(itertools.permutations('abc',2)))

print('------------------------------------')

print(list(itertools.combinations('abc',2)))
1
4
7
------------------------------------
a
b
a
b
a
b
------------------------------------
[3, 3, 3]
------------------------------------
[1, 3, 2, 3]
------------------------------------
[1, 2, 8, 9]
------------------------------------
[18, 19]
------------------------------------
0
1
0
1
------------------------------------
[('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]
------------------------------------
[('a', 'b'), ('a', 'c'), ('b', 'c')]

9.2 生成器

9.2.1 生成器创建

生成器对象是通过yield关键字定义的函数对象,生成器也是一个函数。

In [27]:

def myYield(n):
    while n > 0:
        print('开始生成:')
        yield n                 #yield用于返回给调用者其后表达式的值,组成一个序列
        print('完成一次。。。')
        n -= 1

if __name__ == '__main__':
    for i in myYield(4):        #遍历生成器
        print('遍历得到的值:',i)
        
    print('---------------------------')
    
    my_yield = myYield(3)       #实例化类
    print('实例化生成器对象',my_yield.__next__())   #调用迭代器中的__next__方法
    print('第二次调用__next__方法:',my_yield.__next__())
    print('第三次调用__next__方法:',my_yield.__next__())
    
    print(type(my_yield))   #查看数据类型,generator生成器的意思
开始生成:
遍历得到的值: 4
完成一次。。。
开始生成:
遍历得到的值: 3
完成一次。。。
开始生成:
遍历得到的值: 2
完成一次。。。
开始生成:
遍历得到的值: 1
完成一次。。。
---------------------------
<generator object myYield at 0x0417E030>
开始生成:
实例化生成器对象 3
完成一次。。。
开始生成:
第二次调用__next__方法: 2
完成一次。。。
开始生成:
第三次调用__next__方法: 1
<class 'generator'>

9.2.2 深入生成器

In [29]:

def myYield(n):
    while n > 0:
        rcv = yield n  #定义了一个rcv来接收调用者传过来的值
        n -= 1
        if rcv is not None:
            n =  rcv

if __name__ == '__main__':
    my_yield = myYield(3)
    print(my_yield.__next__())
    print(my_yield.__next__())
    print('传给生成器一个值,重新初始化生成器。')
    print(my_yield.send(10))  #使用send方法传递值,也称为协程,看下一小节
    print(my_yield.__next__())
3
2
传给生成器一个值,重新初始化生成器。
10
9
    还可以使用一个类似列表推导的生成器表达式

In [35]:

a = (i for i in range(5))
a
print(type(a))
list(a)   #注意可以使用list()将其转化为列表,主句量太大和无序,不建议转化,会导致死机
<class 'generator'>

Out[35]:

[0, 1, 2, 3, 4]

9.2.3 生成器与协程

协程是一种解决程序并发的方法。

In [38]:

def consumer():
    print('等待接收处理任务')
    while True:
        data = (yield)
        print('收到任务:',data)
        
def producer():
    c = consumer()
    c.__next__()
    for i in range(3):
        print('发送一个任务...','任务%d' % i)
        c.send('任务%d' % i)
        
producer()   #if __name__ == '__main__'这段其实可以不用写,忘记什么时候写请参看之前内容
等待接收处理任务
发送一个任务... 任务0
收到任务: 任务0
发送一个任务... 任务1
收到任务: 任务1
发送一个任务... 任务2
收到任务: 任务2

9.3 装饰器

9.3.1 装饰器概述

为了个不同的函数或类插入相同的功能
‘@’符号来实现
使用装饰器装饰对象,必须要先定义装饰器,装饰器的定义与普通函数的定义在形式上完全一致,只不过装饰器函数的参数必须要有函数或类对象,然后再装饰器函数中重新定义一个新的函数或类,并在其中执行某些功能前后或中间来使用被装饰的函数或类,最后返回这个新定义的函数或类。

In [39]:

def demo_decorater(fun):
    def new_fun(*args,**kwargs):
        pass
        fun(*args,**kwargs)
        pass
    return new_fun  #完全摸不到头脑,看下例

9.3.2 装饰函数

In [43]:

#这个列子好看的多了
def abc(fun):
    def wrapper(*args,**kwargs):
        print('开始...')
        fun(*args,**kwargs)
        print('结束')
    return wrapper
    
@abc
def demo_decoration(x):
    a = []
    for i in range(x):
        a.append(i)
        print(a)
        
@abc
def hello(name):
    print('hello ',name)
    
demo_decoration(5)
print()
hello('默天')
开始...
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
结束

开始...
hello  默天
结束

9.3.3 装饰类

In [70]:

def abc(myclass):
    class InnerClass:
        def __init__(self,z=0):
            self.z = 0
            self.wrapper = myclass()
        def position(self):
            self.wrapper.position()
            print('z axis:',self.z)
    return InnerClass

@abc
class coordination:
    def __init__(self,x=0,y=0):
        self.x = x
        self.y = y       
    def position(self):
        print('x axis:',self.x)
        print('y axis:',self.y)
        
if __name__ == '__main__':
    coor = coordination()
    coor.position()
x axis: 0
y axis: 0
z axis: 0

转载于:https://my.oschina.net/zhackj/blog/1634105

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值