zoukankan      html  css  js  c++  java
  • python学习第四天

    一、迭代器

    1.Iterable(可迭代的)

    我们已经知道可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型:list tuple dict set str 等

    一类是generator 包括生成器和带yield的generator function

    这些可以直接作用于for循环的对象统称为可迭代对象 Iterable

    可以使用isinstance()判断一个对象是否是Iterable对象

    form collections import Iterable

    isinstance([ ],Iterable)

    true

    2.Iterator(迭代器)

    而生成器不但可以作用于for循环还可以被next()函数不断调回并返回下一个值 直到最后抛出 stopIteration 错误表示无法继续返回下一个值了

    可以被next()函数调用并不断返回的下一个值的对象统称为Iterator迭代器

    同样可以使用isinstance()判断一个对象是否是Iterator对象

    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True

    Python的for循环本质上就是通过不断调用next()函数实现的,例如:

    for x in [1, 2, 3, 4, 5]:
        pass
    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    # 循环:
    while True:
        try:
            # 获得下一个值:
            x = next(it)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break

    二、生成器

    参考:https://blog.csdn.net/weixin_37720172/article/details/78482291

    假设某列表元素过于庞大 而且可以通过固定的算法实现 这种一边循环一边计算的机制 被称为 生成器 generator

    我们可以用列表生成式来生成一个列表

    l=[x for x in range(5)] 
    print (l)
    
    [0, 1, 2, 3, 4]

    我们可以用类似的方式生成一个生成器

    g=(x for x in range(5))
    print g
    
    <generator object <genexpr> at 0x000000000396D360>

    可以看到它返回一个生成器

    那么怎么返回这个生成器的值呢? 有两种方法

    >>> for m in g:print m
    ...
    0
    1
    2
    3
    4
    
    >>> g=(x for x in range(5))
    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    2
    >>> next(g)
    3
    >>> next(g)
    4
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

    生成器在面对庞大的列表时 会大量的节省内存空间 下面这段代码就可以验证一波

    import time
    
    def get_time(func):
        def wraper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            print("Spend:", end_time - start_time)
            return result
        return wraper
    
    @get_time
    def _list(n):
        l1 = [list(range(n)) for i in range(n)]
        del l1
    
    
    @get_time
    def _generator(n):
        ge = (tuple(range(n)) for i in range(n))
        del ge
    
    _list(1000)
    _generator(1000)
    

     

    ('Spend:', 0.026999950408935547)
    ('Spend:', 0.0)

    生成器中yield的使用:

    yield就是专门给生成器用的return yield的作用在于保存一个generator的状态

    还可通过yield实现在单线程情况下实现并发运算的效果

    import time
    def consumer(name):
        print '%s开始' %name
        while True:
            baozi = yield
            print '%s来了%s吃了' %(baozi,name)
    def producter(name):
        c=consumer('A')
        c1=consumer('B')
        c.next()
        c1.next()
        print 'begin!'
        for i in range(10):
            time.sleep(1)
            c.send(i)
            c1.send(i)
    producter('C')
    yield实现异步

    一个函数中含有yield的话 默认调用这个函数的为生成器

    yield 可以通过send接收数据

    三、装饰器

    对已有功能的扩展 不改变源代码 

    @函数名 称为语法糖  程序执行到语法糖后 会执行此函数 并且以该语法糖下面的函数作为 参数

    @函数名 该语法糖中的函数 至少有两层 第一层接收函数 第二层接收 语法糖下面函数所传的参数

    注:被装饰的函数所携带的参数

    #一个参数
    def w1(func):
        def inner(arg):
            # 验证1
            # 验证2
            # 验证3
            return func(arg)
        return inner
    
    @w1
    def f1(arg):
        print 'f1'
    
    #二个参数
    def w1(func):
        def inner(arg1,arg2):
            # 验证1
            # 验证2
            # 验证3
            return func(arg1,arg2)
        return inner
    
    @w1
    def f1(arg1,arg2):
        print 'f1'
    
    #n个参数
    def w1(func):
        def inner(*args,**kwargs):
            # 验证1
            # 验证2
            # 验证3
            return func(*args,**kwargs)
        return inner
     
    @w1
    def f1(arg1,arg2,arg3):
        print 'f1'
    
    #
    参数

    一个函数被多个装饰器装饰

    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'

    四、递归

    函数执行过程中调用函数本身

     注:递归要有一个明确的出口

    递归算法的效率较低 每次递归都要在内存中保存一次函数体

    五、简单算法

    1、二分查找

    def binary_search(data_source,find_s):
        print data_source
        mid=len(data_source)/2
        if len(data_source) >= 1:
            if data_source[mid] > find_s:
                print '%s is in %s left' %(find_s,data_source[mid])
                binary_search(data_source[:mid],find_s)
            elif data_source[mid] < find_s:
                print '%s is in %s right' % (find_s, data_source[mid])
                binary_search(data_source[mid:], find_s)
            else:
               print  'find %s' %data_source[mid]
        else:
            print 'cant find'
    
    
    if __name__ == '__main__':
        data=list(range(1,600,3))
        binary_search(data,1)
    二分法递归查找

    2、二维列表90度旋转

    # a=[i for i in range(4)]
    # print a
    a=[[i for i in range(4)]for j in range(4)]
    # print a
    #for b in a:print b
    for b_index,b in enumerate(a):
        #print b,b_index
        for l in range(b_index,len(b)):
            tmp=a[b_index][l]
            a[b_index][l]=a[l][b_index]
            a[l][b_index]=tmp
            for c in a :print c
            print '------'
    列表顺时针选装90度

    涉及到列表的下标  可以使用range(len(列表名))

    六、python正则

    字符:

      . 匹配除换行符以外的任意字符
      w 匹配字母或数字或下划线或汉字
      s 匹配任意的空白符
      d 匹配数字
       匹配单词的开始或结束
      ^ 匹配字符串的开始
      $ 匹配字符串的结束

    次数:

      * 重复零次或更多次
      + 重复一次或更多次
      ? 重复零次或一次
      {n} 重复n次
      {n,} 重复n次或更多次
      {n,m} 重复n到m次

    re.search    search,浏览整个字符串去匹配第一个,未匹配成功返回None

    re.findall      findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖; 空的匹配也会包含在结果中

    re.match match  从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None

    七、python实现简单计算器

    #-*- coding:utf-8-*-
    import re
    def fg(sz):
    
        sz2=[ ]
        sz3=[ ]
    
        for sz_index,i in enumerate(sz1):
            if i=='(':
                ks=sz_index+1
            elif i==')':
                js=sz_index
                for j in range(ks,js):
                    sz2.append(sz1[j])
                    if j == js-1:
                        cc(sz2)
                        for d in range(ks - 1, js + 1):
                            sz1.pop(ks-1)
                        for x in sz2:
                            sz1.insert(ks-1,x)
                        fg(sz1)
                        cc(sz1)
                        sz3=jj(sz1)
                        return sz3[0]
    def jj(sz3):
        for p_index,p in enumerate(sz3):
            if p == '+':
                n1=int(sz3[p_index-1])
                n2=int(sz3[p_index+1])
                n=n1 + n2
                #print n
                n = str(n)
                sz3.insert(p_index-1,n)
                sz3.pop(p_index)
                sz3.pop(p_index)
                sz3.pop(p_index)
                #print sz3
                jj(sz3)
            if p == '-':
                n1=int(sz3[p_index-1])
                n2=int(sz3[p_index+1])
                n=n1 - n2
                n = str(n)
                sz3.insert(p_index-1,n)
                sz3.pop(p_index)
                sz3.pop(p_index)
                sz3.pop(p_index)
                jj(sz3)
        #print sz3
        return sz3
    
    def cc(sz2):
        for l_index,l in enumerate(sz2):
            if l == '*' :
                m1=int(sz2[l_index-1])
                m2=int(sz2[l_index+1])
                m=m1 * m2
                m = str(m)
                sz2.insert(l_index-1, m)
                sz2.pop(l_index)
                sz2.pop(l_index)
                sz2.pop(l_index)
                cc(sz2)
            elif l == '/':
                m1 = int(sz2[l_index - 1])
                m2 = int(sz2[l_index + 1])
                m = m1 / m2
                m=str(m)
                sz2.insert(l_index - 1, m)
                sz2.pop(l_index)
                sz2.pop(l_index)
                sz2.pop(l_index)
                cc(sz2)
        #print sz2
        return sz2
    
    if __name__== '__main__':
        ss=raw_input('请输入:')
        sz1 = re.findall('[0-9]+|*|/|+|-|(|)',ss)
        print fg(ss)
    计算器 带括号
  • 相关阅读:
    滑动窗口(单调队列)
    蒜头君的排序
    P2024 食物链
    STL
    P2880 [USACO07JAN]平衡的阵容Balanced Lineup(RMQ的倍增模板)
    LCA的两种写法
    P1439 最长公共子序列(nlognLCS问题)
    P3383 【模板】线性筛素数
    P2158 [SDOI2008] 仪仗队(欧拉函数模板)
    alifhab
  • 原文地址:https://www.cnblogs.com/gzcheng/p/9583256.html
Copyright © 2011-2022 走看看