zoukankan      html  css  js  c++  java
  • 20181203(迭代器,生成器,函数的递归调用和二分法)

     

    1、迭代器

    什么是迭代器:

    迭代取值的工具。迭代是一个重复的过程,但是每次重复都是基于上一次重复的结果而继续。

    为什么要用迭代器:

    迭代器的优点:

    1、提供了一种不依赖索引的迭代取值方式

    2、更节省内存

    迭代器的缺点:

    1、不如按照索引的取值方式灵活

    2、取值是一次性的,只能往后去,无法预测值的个数

    如何用迭代器:

    可迭代的对象:strlist upledictset文件对象

    但凡内置有__iter__方法的对象都称之为可迭代的对象。

    迭代器的对象:文件对象

    即内置有__iter__方法又内置有__next__方法的对象都称之为迭代器对象。

     

    调用可迭代对象下__iter__方法,会有一个返回值,该返回值就是内置的迭代器对象。

     

    for循环的底层工作原理

    1、调用in后面的那个值/对象的__iter__方法,拿到一个迭代器对象iter_obj

    2、调用迭代器对象iter_obj.__next__()将得到的返回值赋值变量名k,循环往复直到取值完毕抛出异常StopIterable

    3、捕捉异常结束循环

    k = {'egon' : '123', 'kevin' : '456'}
    iter_k = k.__iter__()   #等同于iter(k)
    while True:
       try:
           v=iter_k.__next__()  #等同于next(iter_k)
           print(v)
       except StopIteration   # 捕捉异常,然后跳出循环
      print('取值完毕')
           break
    两种方法
    for i in k:
       print(i)

     

    迭代器下面的两个函数。iter()和next() 。

    d={'k1':111,'k2':222,'k3':333}

    print(d.__iter__().__next__())
    print(d.__iter__().__next__())
    print(d.__iter__().__next__())
    此处三个结果都为:k1

    d=iter(d)
    print(d.__next__())
    print(d.__next__())
    print(d.__next__())
    此时输出结果为:k1,k2,k3

     

    2、生成器

    生成器就是一种自定义的迭代器

    如何得到生成器:

    但凡函数内出现yield关键字,再去调用函数不会立即执行函数体代码,会得到一个返回值,该返回值就是生成器对象。

    def func():
       print('first')
       yield 1
       print('second')
       yield 2
       print('third')
       yield 3


    g=func()
    print(g)

    res1=next(g)
    print(res1)

    res2=next(g)
    print(res2)

    res3=next(g)
    print(res3)
    输出结果为:
    <generator object func at 0x00000235ECE3DEB8>
    first
    1
    second
    2
    third
    3

     

    总结yield:

    1、提供一种自定义迭代器的解决方案

    2、yield & return

    相同点:都可以返回值,返回值没有类型限制个数限制

    不同点:return只能返回一次值,yield却可以让函数暂停在某一个位置,可以返回多次值。

     

    3、函数的递归调用和二分法

    1、函数的递归调用:

    在调用一个函数的过程又直接或间接调用了函数本身,称之为递归调用

    递归必须满足两个条件:

    1、每进入下一次递归调用,问题的规模都应该有所减少

    2、递归必须有一个明确的结束条件

    递归关键在于将问题分解为小部分,总是以最小可能性问题结束。

    递归有两个明确的阶段:

    1、回溯

    2、递推

    求阶乘的计算
    def fake(n):
       if n==1:
           return 1
       return  n*fake(n-1)

    print(fake(5))
    输出结果为:
    120

     

    def age(n):
       if n == 1:
           return 18
       return age(n-1)+2

    print(age(5))
    输出结果为26

    其内在逻辑为
    # age(5)=age(4)+2
    # age(4)=age(3)+2
    # age(3)=age(2)+2
    # age(2)=age(1)+2
    # age(1)=18

    # age(n)=age(n-1)+2 # n > 1
    # age(1)=18         # n = 1

    解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环效果是一样的,把循环看成是一种特殊的尾递归函数也可以。

    求阶乘的计算
    def fact(n):
       return inner(n,1)

    def inner(num1,num2):
       if num1==1:
           return num2
       return inner(num1-1,num2*num1)
    print(fact(5))
    输出结果为:
    120

    修改为也可
    def inner(num1,num2):
       if num1==1:
           return num2
       return inner(num1-1,num2*num1)
    print(inner(5,1))

     

    递归调用与二分法的结合:

    nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341]


    def binary_search(list1,find_num):
       print(list1)
       if len(list1) == 0:
           print('not exist')
           return
       mid_index=len(list1) // 2
       if find_num > list1[mid_index]:
           # in the right
           binary_search(list1[mid_index + 1:],find_num)
       elif find_num < list1[mid_index]:
           # in the left
           binary_search(list1[:mid_index],find_num)
       else:
           print('find it')

    binary_search(nums,203)

    输出结果为:
    [3, 5, 7, 11, 13, 23, 24, 76, 103, 111, 201, 202, 250, 303, 341]
    [103, 111, 201, 202, 250, 303, 341]
    [250, 303, 341]
    [250]
    []
    not exist

     

     

  • 相关阅读:
    动态规划小练
    组合计数小练
    【WC2019】 通道
    【PKUSC2018】主斗地
    【NOI2009】诗人小G
    【THUWC 2017】随机二分图
    【NOI2017】游戏与2-sat方案输出
    Codeforces 1109D sasha and interesting fact from graph theory
    Codeforces 1152E neko and flashback
    ZJOI2019游记
  • 原文地址:https://www.cnblogs.com/realadmin/p/10059482.html
Copyright © 2011-2022 走看看