python基础6-文件操作/迭代器/for循环/生成器

  • 文件读操作

  • windows的文件是以gbk存储的
  • f = open('陈粒', ‘r’, encoding='utf-8'),以utf-8编码
  • 在pycharm创建文件,在右下角选择编码方式,gbk
  • 就是应用程序➡️通过操作系统➡️获得管理硬盘数据的渔网,就叫文件句柄
  • 记得关闭文件
  • f.read()读出来是str文件
  • f.readable(),判断文件是否可读
  • f.readline(),一次读一行
  • f.readlines(),把文件读取成列表格式
  • 文件写操作

  • f.writelines(['555\n','666\n']),将列表按照一行一行写入文件f指的文件
  • 写的东西都是字符串,不能是数字
  • 用w和w+都是新建立一个文件,如已经有,则清空
  • 文件追加操作append

  • 文件没有修改一说,全都是覆盖,因为在硬盘上都是二进制存储。
  • 从硬盘中读取文件,在内存中修改,然后覆盖到硬盘上
  • with open('a.txt', 'w') as f: f.write('11111\n'),打开文件自动关闭
  • 文件处理b模式

  • rb的方式对linux没有任何用处,一切皆文件,linux全都是用二进制处理。但是windows不都是二进制,rb的b是bytes,字节方式
  • 8个二进制bit是1个字节bytes。字节本质上就是二进制
  • b的方式不能指定编码模式,f=open('test11.py', 'rb'),以二进制形式打开py文件,要想显示字符,还需解码,data.decode('utf-8')
  • f=open('test22.py','wb'),f.write(bytes('111\n', encoding='utf-8')),以wb打开文件,写入时要将字符串通过bytes转换为二进制编码写入。或者直接x.encode('utf-8')
  • b的方式,用来处理图片视频。二进制方法可以跨平台,跨系统
  • 文件操作的其他方法

  • f.closed,检测文件是否关闭
  • f.encoding,获取文件打开的编码,不同平台对utf-8代号不同
  • 文件1以utf-8编码,不能用其他编码读取,但可以用gbk等其他编码写入新东西
  • 不清楚文件编码时,可以使用f=open('b.txt' , 'r' ,encoding='latin-1')万能编码。忽略
  • f.flush(),把数据从内存刷新到硬盘上
  • f.tell()读取文件中的光标位置
  • f=open('b.txt','r',encoding='utf-8', newline=''),使用newline读取文件中真正的换行符号
  • 只有f.read(3)是3个字符,即'a','b'为单位,其余的文件内光标移动都是以字节为单位,如f.seek,f.tell,f.truncate,f.readline
  1. ASCII码中,一个英文字母(不分大小写)为一个字节,一个中文汉字为两个字节
  2. UTF-8编码中,一个英文字母为一个字节,一个中文为三个字节。
  • f.truncate(10)是一种文件的写操作,截取操作,将文件只保留从0-10个字节的内容
  • f.seek()用来移动光标
  • 文件seek方法补充

  • seek(10,1),相对位置seek,前提是用rb打开文件,二进制执行
  • seek(-10,2),从文件末尾开始seek,是倒叙
  • 故障检查要查看最新的日志。
  1. 不用seek方法,data= f.readlines(),print(data[-1], decode('utf-8')),readlines读取文件每一行,然后打印最后一行
  2. 循环文件的推荐方式:for i in f: 一次一行,要一行给一行,而不是存储一个大列表。设置一个偏移量offs,seek(offs, 2),从末尾开始,每次一个offs
    for i in f:
        offs = -10
        while True:
            f.seek(offs,2)
            data = f.readlines()
            if len(data) >1:
                print('文件的最后一行是%s' %(data[-1].decode('utf-8')))
                break
            offs*=2#如果不执行if,则加大偏移量,用于下次循环
  • data是个列表,len(data)是指列表的行数
  • 迭代器

  • 迭代和递归的区别
  1. 递归,问路,是甲问乙,乙问丙,丙问丁,丁告诉丙,丙告诉乙,乙告诉甲
  2. 迭代,是甲问乙,乙让甲问丙,甲问丙,丙让甲问丁,甲问丁,得到结果
  • 迭代器协议,对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代,即只能往下一步走,不能往后退。
  • 可迭代对象,实现了迭代器协议的对象
  • 字符串,列表,字典等for循环对象本身都不是可迭代对象,for循环先调用字符串/列表的_iter_方法,将其转换为可迭代对象,然后就有了next方法,最后捕捉异常
  • l = [1, 2, 3]
    iter_l=l.__iter__()#遵循迭代器协议,将列表生成可迭代对象
    print(iter_l.__next__())
    #for循环的机制跟索引没有一点关系,for循环就是基于迭代器协议工作的
  • 基于索引和while只能遍历字符串/列表/元组等有下标的对象,for循环才能遍历字典/集合/文件对象。for循环处理字典时,迭代的是字典的key值,这是因为__iter__._next_就是key值
  • print(next(iter_1)),next()是python内置函数,_iter_next_是数据对象内置的,next()本质就是在调用iter_l.next()方法
  • 迭代器就是可迭代对象
  • 生成器

  • 可以理解为一种数据类型,自动实现了迭代器协议,不用iter方法,直接调用.__next__方法

  • 函数中只要有yield,得到的就是生成器。yield相当于return,但是可以yield多次,可以保留函数运行状态,用next继续执行
  • 三元表达式和列表解析
  1. 三元表达式,'SB' if name == 'alex' else '帅哥',如果if成立,返回SB,否则返回“帅哥”
  2. 列表解析,l=['鸡蛋%s' %i  for i in range(10) ],生成['鸡蛋0','鸡蛋1'.....]的列表,中括号是列表解析式,小括号就是生成器表达式
  3. l1 = ['鸡蛋%s' %i for i in range () if i>5],这也是三元表达式,没有4元表达式
  • 生成器表达式:laomuji = ('鸡蛋%s' %i for i in range(10)),laomuji也是生气器对象。
  • sum,map,filter都是迭代器协议
  • 生成器函数的好处,1不占空间,2效率高
  • 生成器特性总结:
  1. 语法上和函数类似,都是使用def定义,生成器使用yield语句返回值
  2. 生成器可以被for循环
  3. 状态挂起,可以保存状态,延续上次操作 
  • def get_population():
        with open('人口普查', 'r', encoding='utf-8') as f:
            for i in f:
                yield i
    g = get_population()
    m = get_population()#用这种方式存储两个迭代器
    all_pop = sum(eval(i)['population'] for i in g)
    print(all_pop)
    for k in m:
        print('%s %%' % ((eval(k)['population'] / all_pop) * 100))
  • 生成者消费者模型

  • 运行生成器的方式
  1. t.__next__()
  2. next(t)
  3. c1.send(‘abc’)从yield开始,把‘abc’赋值给yield,然后像__next__一样开始推动程序执行。
  • yield 3相当于return,控制的是函数的返回值
  • x= yield的另外一个特性,接受send传过来的值,赋值给x
  • 使用send,在一个程序中实现并发操作
  • import time
    def consumer(name):
        print('我是[%s],我准备开始吃包子了' %name)
        while True:
            baozi=yield
            time.sleep(1)
            print('%s 很开心的把[%s]吃掉了'%(name, baozi))
    
    def producer():
        c1=consumer('wupeiqi')
        c2=consumer('yuanhao_sb')
        c1.__next__()
        c2.__next__()
        for i in range(10):
            time.sleep(1)
            c1.send('包子 %s' %i)#通过send调用consumer函数
            c2.send('包子 %s' %i)
    producer()
  • 异步携程
posted @ 2022-01-10 17:08  线索  阅读(169)  评论(0编辑  收藏  举报