zoukankan      html  css  js  c++  java
  • python16_day05【迭代器、生成器、模块】

    一、列表生成式

      1.我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 :

    >>> a
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> b = []
    >>> for i in a:b.append(i+1)
    ... 
    >>> b
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    >>> a = b
    >>> a
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    普通青年版
    
    
    a = [1,3,4,6,7,7,8,9,11]
    
    for index,i in enumerate(a):
        a[index] +=1
    print(a)
    
    原值修改
    

      2.Map版本

    >>> a
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    >>> a = map(lambda x:x+1, a)
    >>> a
    <map object at 0x101d2c630>
    >>> for i in a:print(i)
    

      3.生成式版(这就叫列表生成式)

    1 >>> a = [i+1 for i in range(10)]
    2 >>> a
    3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    二、生成器

    通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
    
    所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

    要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

    列表生成式:[]
    生成器:()
    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>
    
    创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
    我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
    如果要一个一个打印出来,可以通过next()函数获得generator的下一个
    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    >>> next(g)
    9
    >>> next(g)
    16
    >>> next(g)
    25
    >>> next(g)
    36
    >>> next(g)
    49
    >>> next(g)
    64
    >>> next(g)
    81
    >>> next(g)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

      

    我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
    当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:
    
    
    >>> g = (x * x for x in range(10))
    >>> for n in g:
    ...     print(n)
    ...
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
    

      斐波那契

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            print(b)
            a, b = b, a + b
            n = n + 1
        return 'done'
    
    
    #注意赋值语句
    a, b = b, a + b
    
    
    将斐波那契变成generator
    def fib(max):
        n,a,b = 0,0,1
    
        while n < max:
            #print(b)
            yield  b
            a,b = b,a+b
    
            n += 1
    
        return 'done' 
    

      使用yield实现异步:

    import time
    def consumer(name):
        print("%s 准备吃包子啦!" %name)
        while True:
           baozi = yield
    
           print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
    
    
    def producer(name):
        c1 = consumer('A')
        c2 = consumer('B')
        c1.__next__()  #这步目地是让consumer函数走到yield这里。
        c2.__next__()
        print("老子开始准备做包子啦!")
        for i in range(10):
            time.sleep(1)
            print("做了2个包子!")
            c.send(i)  #这步很重要。1.为了唤醒yield。2.为了将i值发送给yield。
            c2.send(i)
    
    producer()
    

      

    三、迭代器

    我们已经知道,可以直接作用于for循环的数据类型有以下几种:
    一类是集合数据类型,如list、tuple、dict、set、str等;
    一类是generator,包括生成器和带yield的generator function。
    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
    可以使用isinstance()判断一个对象是否是Iterable对象
    

      

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

      

    """
        1.生成器:可以被for循环. [],{},(),                   generator
        2.迭代器:不但可以被for循环,还可以next.   yield        Iterator
    """
    

      

    生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
    
    把list、dict、str等Iterable变成Iterator可以使用iter()函数:
    
    
    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True
    

      

    你可能会问,为什么list、dict、str等数据类型不是Iterator?
    
    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
    
    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
    
     
    

      

    小结
    
    凡是可作用于for循环的对象都是Iterable类型;
    
    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
    
    集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
    
    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
    

    

    四、模块

      1.time模块

    #_*_coding:utf-8_*_
    
    import time
    
    
    # print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来
    # print(time.altzone)  #返回与utc时间的时间差,以秒计算
    # print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",
    # print(time.localtime()) #返回本地时间 的struct time对象格式
    # print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式
    
    # print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016",
    #print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上
    
    
    
    # 日期字符串 转成  时间戳
    # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式
    # print(string_2_struct)
    # #
    # struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳
    # print(struct_2_stamp)
    
    
    
    #将时间戳转为字符串格式
    # print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式
    # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式
    
    
    
    
    
    #时间加减
    import datetime
    
    # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
    #print(datetime.date.fromtimestamp(time.time()) )  # 时间戳直接转成日期格式 2016-08-19
    # print(datetime.datetime.now() )
    # print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
    # print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
    # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
    # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
    
    
    #
    # c_time  = datetime.datetime.now()
    # print(c_time.replace(minute=3,hour=2)) #时间替换
    

      

      2.random模块

      

    import random
    print random.random()
    print random.randint(1,2)
    print random.randrange(1,10)
    
    
    #生成随机码 1
    import random
    checkcode = ''
    for i in range(4):
        current = random.randrange(0,4)
        if current != i:
            temp = chr(random.randint(65,90))
        else:
            temp = random.randint(0,9)
        checkcode += str(temp)
    print checkcode
    
    #生成随机码 2
    import random
    import string
    
    # print(random.randint(1, 10))
    # print(random.randrange(1, 20, 2))
    # print(random.sample(range(100), 5))
    
    def check_code(num):
        source = string.digits + string.ascii_letters
        print("".join(random.sample(source, num)))
    
    check_code(6)
    

      3.OS模块

      

    os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
    os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
    os.curdir  返回当前目录: ('.')
    os.pardir  获取当前目录的父目录字符串名:('..')
    os.makedirs('dirname1/dirname2')    可生成多层递归目录
    os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
    os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
    os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
    os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
    os.remove()  删除一个文件
    os.rename("oldname","newname")  重命名文件/目录
    os.stat('path/filename')  获取文件/目录信息
    os.sep    输出操作系统特定的路径分隔符,win下为"\",Linux下为"/"
    os.linesep    输出当前平台使用的行终止符,win下为"	
    ",Linux下为"
    "
    os.pathsep    输出用于分割文件路径的字符串
    os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
    os.system("bash command")  运行shell命令,直接显示
    os.environ  获取系统环境变量
    os.path.abspath(path)  返回path规范化的绝对路径
    os.path.split(path)  将path分割成目录和文件名二元组返回
    os.path.dirname(path)  返回path的目录。其实就是os.path.split(path)的第一个元素
    os.path.basename(path)  返回path最后的文件名。如何path以/或结尾,那么就会返回空值。即os.path.split(path)的第二个元素
    os.path.exists(path)  如果path存在,返回True;如果path不存在,返回False
    os.path.isabs(path)  如果path是绝对路径,返回True
    os.path.isfile(path)  如果path是一个存在的文件,返回True。否则返回False
    os.path.isdir(path)  如果path是一个存在的目录,则返回True。否则返回False
    os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
    os.path.getatime(path)  返回path所指向的文件或者目录的最后存取时间
    os.path.getmtime(path)  返回path所指向的文件或者目录的最后修改时间
    

      4.sys模块

    sys.argv           命令行参数List,第一个元素是程序本身路径
    sys.exit(n)        退出程序,正常退出时exit(0)
    sys.version        获取Python解释程序的版本信息
    sys.maxint         最大的Int值
    sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
    sys.platform       返回操作系统平台名称
    sys.stdout.write('please:')
    val = sys.stdin.readline()[:-1]
    

      5.json and pickle

      http://www.cnblogs.com/weibiao/p/6273652.html

      6.logging模块

      

    import logging
    from logging import handlers
    
    # create logger
    logger = logging.getLogger('TEST-LOG')
    logger.setLevel(logging.ERROR)
    
    # create console handler and set level to debug
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    
    # create file handler and set level to warning
    #根据时间截断
    # fh = handlers.TimedRotatingFileHandler("access.log",when="S",interval=5,backupCount=3)
    #根据文件截断
    fh = handlers.RotatingFileHandler("access.log", maxBytes=4, backupCount=2)
    fh.setLevel(logging.WARNING)
    
    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    # add formatter to ch and fh
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    
    # add ch and fh to logger
    logger.addHandler(ch)
    logger.addHandler(fh)
    
    # 'application' code
    logger.debug('debug message')
    logger.info('info message')
    logger.warn('warn message')
    logger.error('error message')
    logger.critical('critical message')
    

      

    五、exec eval compile

    1.exec
        exec("for i in range(10): print(i)")
    
    2.eval
        1>string计算
            a = 8
            eval("3 * a")
            24
        2>string转成字典
            s = '{1:11,2:22}'
            eval(s)
    
    3.compile
        eval(compile("1+2",'eval'))
        exec(compile("1+2",'exec'))
    

    六、json

      import json
    1
    1.dumps and loads 2 data={"name":"tom",'age':18} 3 json_string = json.dumps(data) # dict转换成json(其实就是字符串) 4 data_dict =json.loads(json_string) # json转换成dict(字符串转字典) 5 6 2.dump and load 7 with open("data.json", 'w') as f: 8 json.dump(data, f) #文件不能写字典(其实就字典转成字符串写文件) 9 10 with open("data.json", 'r') as f: 11 data = json.load(f) #从文件读出字符串(json),转成字典。
  • 相关阅读:
    关于根据索引 删除队
    Vs 2012 编译C 语言
    动态绑定 dgvlist 列
    自定义控件闪烁问题
    程序员都不读书,但你应该读
    对于委托的理解 委托和事件
    ​label 中 文字的位置
    vs2010 折叠C/c++中的if
    关于动态创建控件性能提高 以及 SuspendLayout & ResumeLayout 的使用
    c# WinForm开发 DataGridView控件的各种操作总结(单元格操作,属性设置)
  • 原文地址:https://www.cnblogs.com/weibiao/p/6421284.html
Copyright © 2011-2022 走看看