zoukankan      html  css  js  c++  java
  • 【python第四日】 文件处理 生成器 迭代器

    文件处理

    input()

    所有输入都是字符串,想变成整数可以这样map(int,str.split())

    文件处理

    打开方式

    •  file=open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

    file:文件名称;
    mode:制定了文件打开的方式,函数提供了如下方式,其中,'rt'为默认方式。
    'r'       open for reading (default)——只读,默认方式
    'w'       open for writing, truncating the file first——写入,会覆盖源文件内容
    'x'       create a new file and open it for writing——创建新文件,并写入内容,如果文件已存在,将会报错:FileExistsError
    'a'       open for writing, appending to the end of the file if it exists——写入,如果文件有内容,则在末尾追加写入
    'b'       binary mode——二进制模式
    't'       text mode (default)——文本模式,默认方式
    '+'       open a disk file for updating (reading and writing)——更新磁盘文件,读写
    'U'       universal newline mode (deprecated)——在paython3中已经弃用
    buffering:用于设置缓存策略
    在二进制模式下,使用0来切换缓冲;在文本模式下,通过1表示行缓冲(固定大小的缓冲区)。
    在不给参数的时候,二进制文件的缓冲区大小由底层设备决定,可以通过io.DEFAULT_BUFFER_SIZE获取,通常为4096或8192字节
    文本文件则采用行缓冲。
    encoding:编码或者解码方式。默认编码方式依赖平台,如果需要特殊设置,可以参考codecs模块,获取编码列表。
    errors:可选,并且不能用于二进制模式,指定了编码错误的处理方式,可以通过codecs.Codec获得编码错误字符串
    newline:换行控制,参数有:None,' ',' ',' '。
    输入时,如果参数为None,那么行结束的标志可以是:' ',' ',' '任意一个,并且三个控制符都首先会被转化为:' ',然后才会被调用;
    如果参数为'',所有的通用的换行结束标志都可以用,但是行结束标识符返回调用不会被编码。
    输出时,如果参数为None,那么行结束的标志可以是:' '被转换为系统默认的分隔符;如果是'',' '则不会被编码。

     windows默认换行符' ',linux默认是' ',如果不设置newline,都会转为' ',但是tell()的时候会变计算' '2个字节,当newline=‘’时候,‘ ’是不转换的,就是这个东西
    closefd:false:文件关闭时,底层文件描述符仍然为打开状态,这是不被允许的,所以,需要设置为ture
    opener:可以通过调用*opener*方式,使用自定义的开启器。底层文件描述符是通过调用*opener*或者*file*, *flags*获得的。
    *opener*必须返回一个打开的文件描述。将os.open作为*opener*的结果,在功能上,类似于通过None。

    #如果在do_something的时候,程序错误就是报出异常错误,但是如果再__exit__()时候return True 则不会报出异常
    class Test:
    
        def __enter__(self):
            print('__enter__() is call!')
            return self
    
        def dosomething(self):
            x = 1/0
            print('dosomethong!')
    
    
        def __exit__(self, exc_type, exc_value, traceback):
            print('__exit__() is call!')
            print(f'type:{exc_type}')
            print(f'value:{exc_value}')
            print(f'trace:{traceback}')
            print('__exit()__ is call!')
            return True
    
    with Test() as sample:
        sample.dosomething()
    
    
    输出如下:
    
    __enter__() is call!
    __exit__() is call!
    type:<class 'ZeroDivisionError'>
    value:division by zero
    trace:<traceback object at 0x034715A8>
    __exit()__ is call!

     json.dump()后面会讲

    read readline readlines

    如果文件很小,read()一次性读取最方便
    如果不能确定文件大小,反复调用read(size)比较保险
    如果是配置文件,调用readlines()最方便;redlines()读取大文件会比较占内存
    如果是大文件,调用redline()最方便
    如果是特殊需求输出某个文件的n行,调用linecache模块
     
    read()  按照字符读取,seek 是按照字节读取,但是如果文件是按照二进制读取就会按照字节read()

    seek tell truncate

     1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

     2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果

      3.seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

    文件方法

    f.close()      关闭文件对象f,并将属性f.close设置为True;
    f.closed       文件已关闭,则返回True;
    f.encoding     byte与str之间进行转换时使用的编码;
    f.fileno()     返回底层文件的文件描述符;
    f.flush()      清空文件对象;
    f.isatty()     如果文件对象与控制台关联,就返回True;
    f.mode         文件对象打开时使用的模式;
    f.name         文件对象f的文件名(如果有);
    f.newlines     文本文件f中的换行字符串的类型;
    f.__next__()   返回文件对象f的下一行;
    f.peek(n)      返回n个字节,而不移动文件指针的位置;
    f.readable()   如果f已经打开等待读取,则返回True;
    f.read(count)  文件对象f中读取至多count个字节,如果没有指定count,就读取从当前文件指针直到最后的每个字节,以二进制模式时,返回bytes对象;以文件模式时,返回str对象;
    f.readinto(ba) 将至多len(ba)个字节读入到bytearray ba中,并返回读入字节数,如果在文件结尾,就为0;
    f.readline(count)      读取下一行,包括
    ;
    f.readlines(sizehint)     读入到文件结尾之前的所有行,并以列表形式返回;
    f.seek(offset,whence)     如果没有给定whence,或其为os.SEEK_SET,就按给定的offset移动文件指针...
    f.seekable()    如果f支持随机存取,就返回True;
    f.tell()      返回当前指针位置;
    f.truncate(size)截取文件到当前文件指针所在位置,如果给定size,就到size大小处;
    f.writable()    如果f是为写操作而打开的,就返回True;
    f.write(s)      将文本对象s写入到文件;
    f.writelines(seq)将对象序列写入到文件;

    文件处理方式

    •   重命名  
      os.rename(current_file_name, new_file_name)
    • 删除文件
      os.remove(file_name)
    • python目录
      os.mkdir("newdir")  创建目录
      os.chdir("newdir")   改变当前目录
      os.getcwd()   获取当前工作目录
      os.rmdir('dirname')  删除目录

    迭代器

    • 凡是可作用于 next() 函数的对象都是 Iterator 类型
    • 迭代器都可以用于for map filter,sorted,max.min循环,但是列表,元组和字符串,字典,zip对象,集合都可以用于for循环,但是不是迭代对象,他是通过__iter__变成可迭代对象

    列表生成式

      三元运算符    值 if x>5 else 否定值      比如   5 if x>5 else 6

            值 for i in range(10)  if i >5    比如  i for i in range(10) 

      矩阵     [[0 for col in range(cols)] for row in range(rows)]

      列表表达式  在三元运算符外面加上【】,[i*5  for i in range(10) ]

    生成器

    生成器是迭代器的一种

    • 函数生成式   待yield    相当于return     x=yield 等待别人到这里需要别人send

    yield:调用foo()得到一个生成器,此时函数内的代码不会执行,当调用next()时,函数被触发执行,碰到yield程序挂起,然后调用g.send(数值),程序从挂起时开始执行,此时数值先给了yield,然后yield赋值给x,程序继续执行,直到碰到yield程序挂起,并将yield后的结果返回给函数。如果此时再次调用next(g)那么yield的值就是None然后赋值给x,程序继续执行,这个效果和g.send(None)一样。So,send的作用有两个:

    1.将值传递给yield,然后yield赋值给x。
    2.触发函数的执行,直到遇到yield停止,yield后的值返回给函数,此步的操作和next()一样。

    def test():
        for i in range(4):
            yield  i
    a  = test()
    t = (i for i in a)
    t1 = (i for i in t)
    print(list(t1))   #生成器只能用一次,谁用完就没有了
    print(list(t))
    #输出如下
    [0, 1, 2, 3]
    []
    def test():
        print("test要开始了")
        yield  1
        print("test运行1处")
        x = yield 2
        print("test 运行:",x)
        yield 4
    
    a = test()
    print("第一次:",a.__next__())
    print("第二次:",a.__next__()) 
    print("第三次:",a.send("10"))  #说明停止在yield 2处,等待下一次接收,
    
    #输出如下
    test要开始了
    第一次: 1
    test运行1处
    第二次: 2
    test 运行: 10
    第三次: 4
    #消费者 生产者模型
    MAX_NUM = 30 SINGLE_MAX=10 s_cons={} jishu={} def consumer(name, num): start = 0 while start <= num : baozi = yield print(f'{name}正在吃第{start+1}个{baozi}') start = start + 1 # del s_cons[name] def producer(): baozizonghe=["素馅包子", "肉馅包子", "豆沙包子"] start = 1 while start < MAX_NUM: baozixuanzhe = random.choice(baozizonghe) for i in s_cons: time.sleep(0.5) if jishu[i] == 0: continue print(jishu) s_cons[i].send(baozixuanzhe) print(f" {i}的倒数第{jishu[i]}个{baozixuanzhe}送完") jishu[i] = jishu[i] - 1 break else: print(f"做了一个{baozixuanzhe},但是没人吃") print("包子卖完了") cons_num = 3 for i in range(cons_num): con_name = "顾客%d" %(i + 1) num_max = random.randint(1,SINGLE_MAX) print(f"{con_name}最大获取{num_max}") jishu[con_name] = num_max tmp = consumer(con_name, num_max) #这一步并不执行任何语句,只是创建一个生成器,需要__next__才到yield地方 tmp.__next__() s_cons[con_name] = tmp print(s_cons) producer()
    • 生成器表达式   用()放在三元运算符外面
    a = (x ** 2 for x in range(1, 10))
    b = (x * x for x in range(1, 11) if x % 2 == 0)
    c = (m + n for m in 'ABC' for n in '123')
    L = (k + '=' + v for k, v in d.items())   

    字符串转字典

    str ="{'one':1,'two':2}" dic = eval(str) print(type(dic),dic) #<class 'dict'> {'one': 1, 'two': 2}

    代码区 

    结论:python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值'来传递对象。

    支付宝     
    您的资助是我最大的动力!
    金额随意,欢迎来赏!
    微信

    如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

    如果,想给予我更多的鼓励,求打       付款后有任何问题请给我留言!!!

    ------------------------------------------------------------------------------------------
    作者:【周sir】
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    2006百度之星
    使用StretchBlt之前一定要用SetStretchBltMode(COLORONCOLOR)
    算法学习建议(转)
    让ARM开发板上SD卡里的程序开机自动运行
    我的Dll(动态链接库)学习笔记
    WinCE 应用程序开机自动运行的又一种方法
    讲讲volatile的作用
    用Platform builder定制WinCE系统
    MFC如何高效的绘图
    利用c语言编制cgi实现搜索
  • 原文地址:https://www.cnblogs.com/zhouguanglu/p/10168784.html
Copyright © 2011-2022 走看看