zoukankan      html  css  js  c++  java
  • 【十】迭代器、生成器、装饰器和标准库

    一:迭代器

    在python中,很多对象可以直接通过for语句来直接遍历,例如:list、string、dict等等,这些被称为可迭代对象

    迭代器是一个可以I记住遍历的位置的对象。

    在python中,支持迭代器协议的就是实现对象的iter()和next()方法。

    • iter()方法返回迭代器本身
    • next()方法返回容器的下一个元素
    • 在结尾时引发stopiteration异常

    迭代器有两个基本的方法:__iter__()和next()方法,一个用来获取迭代器对象,一个用来获取容器中的下一个元素

    In [1]: l=[1,2,3,4,54]
    In [2]: it=iter(l)
    #通过iter()方法获得了list的迭代对象
    In [3]: it
    Out[3]: <list_iterator at 0x7f4242c89e10>
    #通过next方法获取下一个元素
    In [4]: next(it)
    Out[4]: 1
    In [5]: next(it)
    Out[5]: 2
    In [6]: next(it)
    Out[6]: 3
    In [7]: next(it)
    Out[7]: 4
    In [8]: next(it)
    Out[8]: 54
    #当容器中没有可访问的元素后,抛出stopiteration异常
    In [9]: next(it)
    ---------------------------------------------------------------------------
    StopIteration                             Traceback (most recent call last)
    <ipython-input-9-2cdb14c0d4d6> in <module>()
    ----> 1 next(it)
    
    StopIteration: 

    其实,当我们使用for语句的时候,for语句会自动通过iter()方法来获得迭代对象,并通过next()方法获取下一个元素

    二:生成器

    生成器是用来创建python序列的一个对象,使用它可以迭代庞大的序列,且不需要在内存中创建和储存整个序列

    #range生成器
    In [10]: sum(range(1,101))
    Out[10]: 5050

    每次迭代生成器,它都会记录上一次调用的位置,并且返回下一个值

    生成器函数和普通函数类似,但是他的返回值使用yield语句声明,而不是return

    生成器是为迭代器产生数据的。

    In [14]: def my_range(first=0,last=10,step=1):
        ...:     number=first
        ...:     while number<last:
        ...:         yield number
        ...:         number+=step
        ...:    
    #这是一个普通的函数     
    >>> my_range
    <function my_range at 0x1070c4e18>
    #返回的是一个生成器对象
    In [15]: my_range()
    Out[15]: <generator object my_range at 0x7f4241b83fc0>
    #对这个生成器对象进行迭代
    In [16]: ranger=my_range(1,5)
    In [17]: for i in ranger:
        ...:     print(i)
        ...:     
    1
    2
    3
    4
    In [18]: print(ranger)
    <generator object my_range at 0x7f424291ea40>
    #在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行 next()方法时从当前位置继续运行。
    In [19]: list(ranger)
    Out[19]: []#因为yield是记住位置的,ranger只里面的内容在for迭代已经全部取出来了,所以这里面为空
    In [20]: ranger=my_range(1,5)
    #还没有进行迭代,所以数据都还存在
    In [21]: list(ranger)
    Out[21]: [1, 2, 3, 4]

    习题:使用生成器写一个斐波纳挈数列

    In [24]: def shulie():
        ...:     num=int(input("请输入一个整数"))
        ...:     f1=0
        ...:     f2=1
        ...:     if num<=0:
        ...:         print("请输入一个正整数")
        ...:     elif num==1:
        ...:         print("斐波纳挈数列:%d"%f1)
        ...:     else:
        ...:         print("斐波纳挈:",end="")
        ...:         for n in range(1,num-1):
        ...:             f=f1+f2
        ...:             f1,f2=f2,f
        ...:             print(f,end="")
        ...:             
    
    In [25]: shulie()
    请输入一个整数0
    请输入一个正整数
    
    In [26]: shulie()
    请输入一个整数1
    斐波纳挈数列:0
    #输出前10项的斐波纳挈数列
    In [29]: shulie()
    请输入一个整数10
    斐波纳挈:12358132134

    三:装饰器

     1.args和*kwargs

    In [46]: def x(*args,**kwargs):
        ...:     print(args) #输出参数的时候不需要加*
        ...:     print(kwargs)
        ...: 
    #从如下例子可以看出,*args就是一个列表,**kwargs就是一个字典    
    In [47]: x(1,2,3)
    (1, 2, 3)
    {}
    In [49]: x(1,2,3,one=1,two=2)
    (1, 2, 3)
    {'two': 2, 'one': 1}
    In [50]: x(one=1,two=2)
    ()
    {'two': 2, 'one': 1}

    2.闭包

    In [51]: def foo(x,y):
    #x,y为自由变量
        ...:     def bar():
        ...:         a=4
        ...:         return x+y+a
        ...:     return bar
        ...: 
    In [52]: bar=foo(1,2)
    In [53]: bar
    Out[53]: <function __main__.foo.<locals>.bar>
    In [54]: bar()
    Out[54]: 7

    3.作为参数的函数

    函数document_it()定义了一个装饰器,需实现如下功能:

    • 打印输出函数的名字和参数值
    • 执行含有参数的函数
    • 打印输出结果
    • 返回修改后的函数
    #装饰器
    In [75]: def documenyt_it(func):
        ...:     def new_func(*args,**kwargs):
        ...:         print("func name",func.__name__)
        ...:         print("args",args)
        ...:         print("kwargs",kwargs)
        ...:         result=func(*args,**kwargs)
        ...:         print("result",result)
        ...:         return result
        ...:     return new_func
        ...: 
    
    In [76]: def add(a,b):
        ...:     return a+b
        ...: 
    
    In [77]: add(3,5)
    Out[77]: 8
    
    In [78]: test_add=documenyt_it(add) #人工对装饰器赋值
    
    In [79]: test_add(3,5)
    func name add
    args (3, 5)
    kwargs {}
    result 8
    Out[79]: 8

     #自己设定装饰器

    #coding=utf-8
    def document_it(func):
        def new_func(*args,**kwargs):
            print('func name',func.__name__)
            print('args',args)
            print('keyword args',kwargs)
            result=func(*args,**kwargs)
            print('result',result)
            return result
        return new_func
    def square_it(func):
        def new_function(*args,**kwargs):
            result=func(*args,**kwargs)
            return result*result
        return new_function
    @square_it  #装饰器
    @document_it
    def add(a,b):
        return a+b
    #注意:打印结果:函数越靠近哪个装饰器就执行那个装饰器内的数据
    print(add(3,5)) 
    #add=add(sqare_it(document_it(add)))

    打印结果:

    C:Python27python.exe "D:/PyCharm Community Edition 5.0.3/代码/ex89.py"
    ('func name', 'add')
    ('args', (3, 5))
    ('keyword args', {})
    ('result', 8)
    64
    
    Process finished with exit code 0

    四:标准库 

    关于标准库的资料:

    1.使用 setdefault() 和 defaultdict() 处理缺失的键

    setdefault():如果键不存在于字典中,将会添加新的键并将值设为默认值(改变了字典)。如果字典中包含有给定键,则返回该键对应的值,否则返回为该键设置的值。

    defaultdict():defaultdict() 返回一个字典,会自动给每个键(key)赋一个初始值

    #coding=utf-8
    d={"l1":1,"l2":2}
    print(d)
    #往d插入一组数据
    d1=d.setdefault("l3",3)
    print(d1)
    #d1返回的结果为value值
    print(d)
    d2=d.setdefault("l3",66)
    #l3已存在,返回已存在key的value值
    print(d2)
    
    from collections import defaultdict
    def no_idea():
        return "huahua"
    #使用工厂方法default_factory给所有key对应的value赋初始值,这些工厂方法有int(), long(), float(), complex(),str(), unicode(), basestring(), 
    t=defaultdict(no_idea)
    t["d1"]=1
    print(t["d2"])
    print(t)
    #如果不用工厂方法,也可以使用自定义方法
    m=defaultdict(lambda :"hub?")
    m["t1"]
    print(m)

    打印信息:

    {'l2': 2, 'l1': 1}
    3
    {'l2': 2, 'l3': 3, 'l1': 1}
    3
    huahua
    defaultdict(<function no_idea at 0x033F5230>, {'d2': 'huahua', 'd1': 1})
    defaultdict(<function <lambda> at 0x033F51F0>, {'t1': 'hub?'})

    例子:针对食物计数

    #coding:utf-8
    #方式1
    from collections import defaultdict
    food_counter=defaultdict(int)
    for food in ["spam","eggs","spam"]:
        food_counter[food]+=1
    print(food_counter)
    #方式2
    d={}
    for food in ["spam","eggs","spam"]:
        if not food in d:
            d[food]=0
            print(d)
        #d[food]+=1
        d[food]=d[food]+1
        print('food',d[food])
    print(d)

    打印结果:

    defaultdict(<type 'int'>, {'eggs': 1, 'spam': 2})
    {'spam': 0}
    ('food', 1)
    {'eggs': 0, 'spam': 1}
    ('food', 1)
    ('food', 2)
    {'eggs': 1, 'spam': 2}

    2.使用 Counter() 计数

    counter:计数器工具用来提供方便快捷的计数支持

    from collections import Counter
    breakfast=['spam','spam','eggs','spam']
    bc=Counter(breakfast)
    print(bc)
    #print(bc.most_common())
    lunch=['eggs','eggs','bacon']
    lc=Counter(lunch)
    print(lc)
    print(bc+lc)

    打印结果:

    Counter({'spam': 3, 'eggs': 1})
    Counter({'eggs': 2, 'bacon': 1})
    Counter({'eggs': 3, 'spam': 3, 'bacon': 1})

    3.使用有序字典 OrderedDict() 按键排序

     OrderedDict: 有序字典

    from collections import OrderedDict
    #有序打印
    quotes=OrderedDict([])
    quotes=OrderedDict([("huahua","my name"),("yuruhao","huhu"),("qq","fere")])
    for i in quotes:
        print(i)

    打印结果:

    huahua
    yuruhao
    qq

    4.使用 pprint() 友好输出

    from pprint import pprint
    qq={
        "h":"huahua",
        "hao":"haohao"
    }
    pprint(qq)

    打印结果:

    {'h': 'huahua', 'hao': 'haohao'}

    例子:判断回文字符串

    #方式一
    def x(word):
        from collections import deque
        dq=deque(word)
        while len(dq)>1:
            if dq.popleft()!=dq.pop():
                return False
            return True
    print(x('a'))
    print(x('abcba'))
    print(x('adsd'))
    #方式二
    def y(words):
        return words==words[::-1] #[::-1]:无头无尾,-1代表步长为-1,倒序
    print(y("asdfdsa"))

    打印结果:

    None
    True
    False
    True
  • 相关阅读:
    笨办法06字符串(string)和文本
    react学习之路-配制antd-mobile
    react.js学习之路六
    bug
    react.js学习之路五
    react.js学习之路四
    react.js学习之路三
    react.js学习之路二
    react.js学习之路一
    MVC,MVP 和 MVVM 的区别之处
  • 原文地址:https://www.cnblogs.com/8013-cmf/p/7128516.html
Copyright © 2011-2022 走看看