• Python之旅的第3²+1天(文件操作、迭代器、生成器)


    今天计划看的一个关于昨天内容的博客最终还是没看,躺下的感觉总是那么爽,爽到你不想起床,但是早晨是例外的,因为精神可以控制肉体。

    首先是关于文件操作的补充:

    # 以字节形式读取文件:
    # f = open('test.txt','rb')  #注意:如果以字节形式读取文件,此时是不能设置encoding =
    # f.close()
    
    # 关于换行,当你以readlines读取文件的时候会获得
    ,但是Python会自动帮你转换为
    
    # 通过在打开文件后面设置上newline
    # f = open('test','r',encoding = 'utf-8')
    # print(f.readlines())   #输出结果:['第二行前面皮一下
    ', 'oujielun
    ', 'kobe
    ', '第二行前面皮一下
    ']
    # f.close()
    #
    # f = open('test','r+',encoding = 'utf-8',newline = '')
    # print(f.readlines())   #输出结果:['第二行前面皮一下
    ', 'oujielun
    ', 'kobe
    ', '第二行前面皮一下
    ']
    # f.close()
    #在open打开文件的时候设置newline默认参数为空后,Python就不会再自动将
    转换为
    
    #但是在使用seek方法的时候,计算字节数时,在Windows中依旧按照
    各自计算一个字节,即换行为两个字节
    
    #字节形式文件写入方法
    # f = open('test_1.txt','wb')    #字节形式写入不能设置encoding哦
    # f.write(bytes('你好啊',encoding = 'utf-8'))  #这里在使用bytes方法输出‘你好啊’对应字节码时是需要注明参考编码表的
    # f.close()
    
    #字节形式读取文件的方式
    # f = open('test_1.txt','rb')   #同理,字节形式读取也是不能在打开文件的时候设置encoding
    # data = f.read()
    # print(data)                  #输出结果:b'xe4xbdxa0xe5xa5xbdxe5x95x8a'('你好啊'的字节形式)
    # print(data.decode('utf-8'))  #输出结果:你好啊
    # f.close()
    
    #为什么会存在用字节形式读取文件的这种反人类操纵呢?
    #我们处理的文件可不仅仅是字符串的形式哦,还有很多照片、视频等文件
    #字节形式可以匹配一切设备,赞。
    
    #文件操作的其他方法
    #closed 检查文件是否关闭,有时候还是会忘记写f.close()
    #f.encoding  显示文件打开所参考的编码(和文件存贮的编码形式无关哦)
    #f.flust  刷新文件,相当于实现文件写入时定期的自动保存功能
    #f.name  获取文件名称(目前感觉好傻逼的方法啊)
    
    #f.tell 显示当前光标读取的所在位置(以字节形式反馈)
    # f = open('test','r+',encoding = 'utf-8')
    # print(f.readline())     #输出结果:'第二行前面皮一下',8个字用utf-8是24个字节,同时加上
    各占一个字节
    # print(f.tell())     #输出结果为:26   3*8+2
    # print(f.closed)     #输出Flase
    # f.close()
    #在文件中的所有读取方法中,只有read是按照字符数的个数进行移动光标,
    # /其他所有方法都是按照字节进行移动光标
    
    # f.seek 非常重要的一个方法,光标的移动
    # 书写的格式为f.seek(a,b)   #按照字节数移动光标
    # a表示光标移动的距离,b表示光标移动的方向
    # 不输入参数b:默认为0,表示从文件最开始的位置移动a个字节
    # b = 1 :表示从光标当前所在位置向后移动a个字节
    # b = 2 :表示光标从文件最后向前移动a个字节,此时的a必须是一个负数
    
    # seek的b值为默认的0时
    # f = open('test','r',encoding = 'utf-8')   #test文件内容
    # ['第二行前面皮一下
    ', 'oujielun
    ', 'kobe
    ', '第二行前面皮一下
    ']
    # print(f.readline())   #输出结果:第二行前面皮一下
    # f.seek(6)             #从文件开始向后移动6个字节
    # print(f.readline())   #此时输出的内容:行前面皮一下
    # f.close()
    
    # seek的b值等于1时,移动光标的相对位置
    # ['第二行前面皮一下
    ', 'oujielun
    ', 'kobe
    ', '第二行前面皮一下
    ']
    # f = open('test','rb')   #test文件内容,忘记了一个很重要的东西,要以字节的方式进行处理
    # f.seek(6,1)             #从文件开始向后移动6个字节
    # print((f.readline()).decode('utf-8'))   #此时输出的内容:行前面皮一下
    # f.seek(6,1)             #上一句的readline已经把光标移动到第二行的开端,现在从第二行开始向后移动6位
    # print((f.readline()).decode('utf-8'))   #此时输出的内容:'un',此时是第二行开始向后移动了6个字节
    # f.close()
    
    # b = 2 时的操作,记住此时的a一定是负数
    # f = open('test','rb')   #test文件内容
    # # ['第二行前面皮一下
    ', 'oujielun
    ', 'kobe
    ', '第二行前面皮一下
    ']
    # f.seek(-6,2)             #从最后向前移动6个字节
    # print((f.readline()).decode('utf-8'))     #此时输出的内容:'一下'
    # f.close()
    
    # seek的b值等于2时,是文件操作中唯一从后向前读取文件的方法
    # 可用于读取大规模文件的最后一行,比如大型网站的管理日志
    # f=open('test_1.txt','rb')
    #
    # for i in f:
    #     offs=-3
    #     n=0
    #     while True:
    #         f.seek(offs,2)
    #         data=f.readlines()
    #         if len(data) > 1:
    #             print('最后一行',data[-1].decode('utf-8'))
    #             break
    #         offs*=2
    
    # 加入没有seek方法,我们读取最后一行文件的方法
    # f = open('test_1.txt','rb')
    # data = f.readlines()    #这个创建list的过程会占用大量内存空间
    # print('最后一行',data[-1].decode('utf-8'))

    关于迭代器:

      迭代器的概念:

    #迭代器即迭代的工具,那什么是迭代呢?
    #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
    while True: #只是单纯地重复,因而不是迭代
        print('===>') 
        
    l=[1,2,3]
    count=0
    while count < len(l): #迭代
        print(l[count])
        count+=1

      为何要有迭代器?什么是可迭代对象?什么是迭代器对象?

    #1、为何要有迭代器?
    对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
    
    #2、什么是可迭代对象?
    可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
    'hello'.__iter__
    (1,2,3).__iter__
    [1,2,3].__iter__
    {'a':1}.__iter__
    {'a','b'}.__iter__
    open('a.txt').__iter__
    
    #3、什么是迭代器对象?
    可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
    而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
    
    文件类型是迭代器对象
    open('a.txt').__iter__()
    open('a.txt').__next__()
    
    
    #4、注意:
    迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象

      迭代器对象的使用

    dic={'a':1,'b':2,'c':3}
    iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
    iter_dic.__iter__() is iter_dic #True
    
    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    print(iter_dic.__next__()) #等同于next(iter_dic)
    # print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
    
    #有了迭代器,我们就可以不依赖索引迭代取值了
    iter_dic=dic.__iter__()
    while 1:
        try:
            k=next(iter_dic)
            print(dic[k])
        except StopIteration:
            break
            
    #这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看for循环

      for循环

    #基于for循环,我们可以完全不再依赖索引去取值了
    dic={'a':1,'b':2,'c':3}
    for k in dic:
        print(dic[k])
    
    #for循环的工作原理
    #1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
    #2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
    #3: 重复过程2,直到捕捉到异常StopIteration,结束循环

      迭代器的优缺点

    #优点:
      - 提供一种统一的、不依赖于索引的迭代方式
      - 惰性计算,节省内存
    #缺点:
      - 无法获取长度(只有在next完毕才知道到底有几个值)
      - 一次性的,只能往后走,不能往前退

     关于生成器:

      什么是生成器

    #只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
    
    def func():
        print('====>first')
        yield 1
        print('====>second')
        yield 2
        print('====>third')
        yield 3
        print('====>end')
    
    g=func()
    print(g) #<generator object func at 0x0000000002184360>

      生成器就是迭代器

    g.__iter__
    g.__next__
    #2、所以生成器就是迭代器,因此可以这么取值
    res=next(g)
    print(res)

      三元表达式

    #三元表达式
    name = input('>>>')
    if name == 'alex':
        print('sb')
    else:
        print('shuaige')
        
    #以上if段落可简写为
    print('sb') if name == 'alex' else print('shuaige')
    
    #貌似还有复杂写法,我得再看看

    其实还是引用了很多现成的内容,暂时就是这么些了,很多需要复习哦

  • 相关阅读:
    06.数组模拟栈-简易计算器
    05.单向环形链表应用 -- 约瑟夫环
    02.数组模拟环形队列
    01.稀疏矩阵与二维数组相互转化
    大数字相乘
    13.打包发布
    悦苗园公益活动
    程序猿打招自己的电子图书馆
    【技能】提高网站可用性
    【微信技能】如何通过微信号知道对方微信的二维码
  • 原文地址:https://www.cnblogs.com/xiaoyaotx/p/12406167.html
Copyright © 2020-2023  润新知