zoukankan      html  css  js  c++  java
  • Python(迭代器 生成器 装饰器 递归 斐波那契数列)

    1、迭代器

    迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件。

    特点:

    1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
    2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
    3. 访问到一半时不能往回退
    4. 便于循环比较大的数据集合,节省内存

    迭代器实例:

    1 name = iter(['chen','a','b','c'])
    2 print(name.__next__())
    3 print(name.__next__())
    4 print(name.__next__())
    5 print(name.__next__())
    6 print(name.__next__()) #最后一次会报错 StopIteration

    2、生成器

    生成器generator

    定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 

    def cash_money(money,num):
        while money > 0:
            money-=num
            yield num,money
            print('又来取钱了啊,败家子!!')
    atm=cash_money(1000,200)
    print('取了%s,还剩下%s'%atm.__next__())
    print('取了%s,还剩下%s'%atm.__next__())
    print('交个大保健')
    print('取了%s,还剩下%s'%atm.__next__())
    print('取了%s,还剩下%s'%atm.__next__())
    '''
    取了200,还剩下800
    又来取钱了啊,败家子!!
    取了200,还剩下600
    交个大保健
    又来取钱了啊,败家子!!
    取了200,还剩下400
    又来取钱了啊,败家子!!
    取了200,还剩下200
    '''
    #这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。
    另外,还可通过yield实现在单线程的情况下实现并发运算的效果,yield也可以接受参数,入下:
    def chi(name,num):
        print('%s来买包子,买%s个'%(name,num))
        while True:
            baozi = yield
            print('包子%s来了,被%s吃了'%(baozi,name))
    def zuo(name,name2):
        A=chi(name,10)
        B=chi(name2,10)
        A.__next__()
        B.__next__()
        print('老子开始做包子了')
        for i in range(1,20,2):
            print('做了两个包子!')
            A.send(i)
            B.send(i+1)
    zuo('','')
    '''
    陈来买包子,买10个
    邱来买包子,买10个
    老子开始做包子了
    做了两个包子!
    包子1来了,被陈吃了
    包子2来了,被邱吃了
    做了两个包子!
    包子3来了,被陈吃了
    包子4来了,被邱吃了
    做了两个包子!
    包子5来了,被陈吃了
    包子6来了,被邱吃了
    做了两个包子!
    包子7来了,被陈吃了
    包子8来了,被邱吃了
    做了两个包子!
    包子9来了,被陈吃了
    包子10来了,被邱吃了
    做了两个包子!
    包子11来了,被陈吃了
    包子12来了,被邱吃了
    做了两个包子!
    包子13来了,被陈吃了
    包子14来了,被邱吃了
    做了两个包子!
    包子15来了,被陈吃了
    包子16来了,被邱吃了
    做了两个包子!
    包子17来了,被陈吃了
    包子18来了,被邱吃了
    做了两个包子!
    包子19来了,被陈吃了
    包子20来了,被邱吃了
    '''

    3、装饰器

    示例1:

    def login(func):
        if 1==1:
         print('passed user verification...')
         return func
        else:
            return aa
    def tv(name):
        print('欢迎来到%s!'%name)
    def aa(aa):
        print('aaaaa')
    tv = login(tv) #可用@login代替 详看下一示例
    tv('Tv')
    '''
    passed user verification...
    欢迎来到Tv!
    '''
    '''
    写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
    封闭:已实现的功能代码块
    开放:对扩展开发'''

    示例2: 再此对上述代码进行优化,装饰利用@

    def login(func):  
        def inner(arg):  
            print('passwd user verification')
            func(arg)  
        return inner
    @login #@login = #tv = login(tv)
    def tv(name):
        print('Welcome %s to tv page!!'%name)
    tv('tv') #等同于# login(tv)('tv')
    '''
    1、用户调用tv('tv')函数,程序检测tv函数上层加有装饰器@login
    2、(这里可以吧装饰器@login理解为执行tv函数之前先@login(login说:谁tm艾特我!),就会执行login函数,func的形参func:(tv你小子艾特我干嘛?tv:我要调用你,则func=tv))
    3、login函数内部加了一个函数,第一次执行将函数加载到内存,login函数return返回结果为函数inner,此时,调用inner函数,用户执行tv的实参('tv')就传入到了inner的形参里
    4、打印密码验证通过,再此可加上判断即可,
    5、inner执行验证完成后调用了func(arg),也就是login的形参 也就是tv('tv') ,现在就调用了tv函数,打印出欢迎登陆信息
    '''

    问题:可以装饰具有处理n个参数的函数的装饰器?

    def w1(func):
        def inner(*args,**kwargs):
            # 验证1
            # 验证2
            # 验证3
            return func(*args,**kwargs)
        return inner
     
    @w1
    def f1(arg1,arg2,arg3): # arg1,arg2,arg3 也可以用*,** 表示
        print 'f1'

    问题:一个函数可以被多个装饰器装饰吗? YES!顺序为按照装饰器的顺序依次执行

    def w1(func):
        def inner(*args,**kwargs):
            # 验证1
            # 验证2
            # 验证3
            return func(*args,**kwargs)
        return inner
     
    def w2(func):
        def inner(*args,**kwargs):
            # 验证1
            # 验证2
            # 验证3
            return func(*args,**kwargs)
        return inner
     
     
    @w1
    @w2
    def f1(arg1,arg2,arg3):
        print 'f1'

    装饰器+参数

    def Before(request,kargs):
        print ('before')
    # print(Before(1,2))
    def After(request,kargs):
        print ('after')
    def Filter(before_func,after_func):
        def outer(main_func):
            def wrapper(request,kargs):
                before_result = before_func(request,kargs)
                # if(before_result != None):
                #     return before_result;
                main_result = main_func(request,kargs)
                # if(main_result != None):
                #     return main_result;
                after_result = after_func(request,kargs)
                # if(after_result != None):
                #     return after_result;
            return wrapper
        return outer
    @Filter(Before, After)
    def Index(request,kargs):
        print ('index')
    if __name__ == '__main__':
        Index(1,2)    #Filter(Before,After)(Index)('1','2')  #   #号后面的解释纯属个人拆分理解
                                    #outer (Index)('1','2')
                                         #wrapper ('1','2')
                                               #Before(1,2)
                                                #Index(1,2)
                                                #After(1,2)

    4、斐波那契数列

    斐波那契(前两个数的值相加等于后面的数的值) 例:

    斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368def func(arg1,arg2,stop):

    List=[]
    def func(a,b,c):
    if a == 0:
    print(a,b)
    d=a+b
    List.append(d)
    if d < c:

    func(b,d,c)
    # print(List)
    func(1,2,50)
    print(List)
    >>> [3, 5, 8, 13, 21, 34, 55]

    5、递归

    特点

    递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
    递归算法解决问题的特点:
    (1) 递归就是在过程或函数里调用自身。
    (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
    (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
    (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。

    要求

    递归算法所体现的“重复”一般有三个要求:
    一是每次调用在规模上都有所缩小(通常是减半);
    二是相邻两次重复之间有紧密的联系,前一次要为后一次做准备(通常前一次的输出就作为后一次的输入);
    三是在问题的规模极小时必须用直接给出解答而不再进行递归调用,因而每次递归调用都是有条件的(以规模未达到直接解答的大小为条件),无条件递归调用将会成为死循环而不能正常结束。
    实现
    1. 通过递归实现2分查找
      现有列表 primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97], 要求尔等 用最快的方式 找出23 。
    def func(yuan,find):
        zhongjian = int(len(yuan) / 2)
        if zhongjian >=1:
            if yuan[zhongjian] > find:
                func(yuan[:zhongjian],find) #func(yuan[:zhongjian],find)
            elif  yuan[zhongjian] < find:
                func(yuan[zhongjian:],find)
            else:
                print('found find',yuan[zhongjian])
        else:
            print('no found')
    if __name__== '__main__':
        data = [2, 3, 5, 7, 8,11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
        print(data)
        func(data,8)
    >>> [2, 3, 5, 7, 8, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, >>>59, 61, 67, 71, 73, 79, 83, 89, 97]
    >>>found find 8
    2分算法思路:
    1、func(data,8)调用函数func 传入的实参为data列表,8
    2、执行函数体, 此时zhongjian函数的值就等于列表data的长度/2 , 假设为300
    3、进行判断此时yuan长度>=1 数据是否还有值,这里等于设置了2分算法的条件
    4、进入判断,原数据的中间值是否比查找的值大, 这里暂定300 > 8 , 因此进入了第一次判断进行的操作
    5、再次执行函数func(yuan[:zhongjian],find) 此时函数体里第一个形参就=600[:300] 大于索引往左切片
    6、之后进行依次循环 如果循环到yuan[zhongjian] < find 则执行<判断里面的函数体知道判断结束
    '''

    算法基础 

    要求:生成一个4*4的2维数组并将其顺时针旋转90度
    第一种偷懒方法(此方法必须要按照一定的顺序格式,)
    data=[[i for i in range(4)] for ii in range(4) ]
    for r_index,row in enumerate(data):
        for c_index in range(len(row)):
            data[r_index][c_index] = row[r_index]
    print(data)
    >>> [[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]

    第二种方法:

    data=[[i for i in range(4)] for ii in range(4) ]
    for r_index,row in enumerate(data):
        for c_index in range(r_index,len(row)):
            tmp = data[c_index][r_index]
            data[c_index][r_index] = row[c_index]
            data[r_index][c_index] = tmp
    print(data)
    
    >>> [[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]
     
  • 相关阅读:
    MinGW-编译器
    Enum , Enum Class ?
    C++编译器之间的不同性能
    交叉验证
    经验风险最小化-结构风险最小化
    图像卷积
    pytorch官网上两个例程
    ORB feature(O for orientation)
    Catalan数
    无责任共享 Coursera、Udacity 等课程视频(转载)
  • 原文地址:https://www.cnblogs.com/Chen-PY/p/5157513.html
Copyright © 2011-2022 走看看