zoukankan      html  css  js  c++  java
  • python进阶与文件处理(数据类型分类,python深浅拷贝,异常处理,字符编码,基本文件操作,绝对路径和相对路径,,高级文件操作,文件的修改)

    数据类型分类

    按存值个数区分

    单个值:数字,字符串

    多个值(容器):列表,元组,字典,集合

    按可变不可变区分

    可变:列表,字典,集合

    不可变:数字,字符串,元组

    有序无序区分

    有序(可按索引取值):字符串,列表,元组

    无序:字典,集合

    Python深浅拷贝

    拷贝:

    当lt2为lt的拷贝对象时,lt内的可变类型变化,lt2变化;lt内的不可变类型变化,lt2变化。(简单的赋值)

    浅拷贝:

    当lt2为lt的浅拷贝对象时,lt内的可变类型变化,lt2变化;lt内的不可变类型变化,lt2不变化。【copy.copy() 可变数据的类型中的内置方法.copy模块】

    深拷贝:

    当lt2为lt的深拷贝对象时,lt内的可变类型变化,lt2不变化;lt内的不可变类型变化,lt2不变。【copy.deepcopy()】

    牢记:

    拷贝/浅拷贝/深拷贝 只针对可变数据类型

    异常处理

    异常是什么?

    异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止)

    一般异常有语法错误逻辑错误

    为什么要异常处理

    为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理

    ①如果错误发生的条件是可预知的,我们可以用if进行处理:在错误发生之前进行预防

    ②如果错误发生的条件是不可预知的,则需要用到try...except:在错误发生之后进行处理

    #基本语法为
    try:
        被检测的代码块
    except 异常类型:
        try中一旦检测到异常,就执行这个位置的逻辑
    

    在try...except中如果你想要的效果是,无论出现什么异常类型,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么就可以使用万能异常Exception

    s1 = 'hello'
    try:
        int(s1)
    except Exception as e:
        print(e)
    

    异常的最终执行

    s1 = 'hello'
    try:
        int(s1)
    except IndexError as e:
        print(e)
    except KeyError as e:
        print(e)
    except ValueError as e:
        print(e)
    #except Exception as e:
    #    print(e)
    else:
        print('try内代码块没有异常则执行我')
    finally:
        print('无论异常与否,都会执行该模块,通常是进行清理工作')
    

    try...except总结

    1. 把错误处理和真正的工作分开来
    2. 代码更易组织,更清晰,复杂的工作任务更容易实现;
    3. 毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了;

    注意

    1. 语法错误无法用try...except捕捉
    2. 逻辑错误可以用try...except捕捉

    了解其他异常处理方法

    抛出异常raise(一般用来自定义异常)

    class EgonException(BaseException):
        def __init__(self, msg):
            self.msg = msg
    
        def __str__(self):
            return self.msg
    
    
    try:
        raise EgonException('抛出异常,类型错误')
    except EgonException as e:
        print(e)
    

    断言assert

    try:
        assert 1 == 2
    except Exception as e:
        print(e)
    

    字符编码

    什么是字符编码

    在计算机内部,所有信息都是由一个个二进制值组成,每一个二进制(bit),有0和1两种状态,因此,8个二进制位可以组合出256种状态,这种称为字节(byte).

    字符编码是将人类的字符编码成计算机能识别的数字.这种转换必须遵循一套固定的标准,该标准无非是人类字符与数字的对应关系,称之为字符编码表。

    字节码与机器码的区别:

    字节码是一种中间状态(中间码)的二进制代码(文件).需要直译器转译后才能成为机器码

    ascii:

    上世界60年代,美国制定了一套字符编码,对英文字符与二进制之间做了联系,这被称为ASCII码,一直沿用至今,ascii码一共规定了128个字符(早期编码,只支持英文字母和一些符号)

    unicode:

    这是一种所有符号的编码,主要作用因为世界上有多种编码方法,同一个二进制数字可以被解释成不同的符号.导致打开一个文本文件时必须用其对应的编码格式,否则会出现乱码.所以就有了unicode诞生.(万国码,能表示多种符号,在PYthon2中可以指定4字节或2字节表示一个字符,PYthon3中默认4字节)

    utf-8:

    最大的特点就是,它是一种变长编码,可以使用1-4个字节表示一个符号,根据不同的符号来变化字节的长度.(用最短的方式表示unicode,一个英文字符占一字节)

    Gbk:

    中文编码。

    内存为什么不用UTF-8呢?

    出现这个问题的原因是硬盘中还躺了其他国家的代码,各个国家的代码的二进制还需要运行在计算机上使用,因此内存中必须使用Unicode的编码,因为Unicode能和硬盘中其他国家的二进制中的代码进行转换,但是UTF-8只是简化了代码的存储,它并不能与其他国家硬盘中的代码进行关系转换。总而言之只有Unicode编码才能运行其他国家硬盘中的代码,而UTF-8的代码无法进行该操作。

    内存中还使用Unicode编码,是因为历史遗留问题造成的,但是因为现在写代码使用的都是UTF-8代码,所以以后内存中的代码都将变成UTF-8代码,并且以前遗留的各个国家的代码都将被淘汰,所以未来内存中使用的编码也将使用UTF-8编码替代Unicode编码。

    总结:

    1. 保证不乱码的核心法则就是,字符按照什么标准而编码的,就要按照什么标准解码,此处的标准指的就是字符编码。
    2. 在内存中写的所有字符,一视同仁,都是Unicode编码,比如我们打开编辑器,输入一个“你”,我们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能很多国家都在使用,根据我们使用的输入法不同这个字的样式可能也不太一样。只有在我们往硬盘保存或者基于网络传输时,才能确定”你“到底是一个汉字,还是一个日本字,这就是Unicode转换成其他编码格式的过程了。简而言之,就是内存中固定使用的就是Uncidoe编码,我们唯一能改变的就是存储到硬盘时使用的编码。
    • Unicode----->encode(编码)-------->gbk
    • Unicode<--------decode(解码)<----------gbk

    基本的文件操作

    打开文件的流程

    如果我们需要打开一个文件,需要向操作系统发起请求,要求操作系统打开文件,占用操作系统资源。Python中使用open()方法可以打开某个具体的文件,open()方法内写入文件路径。

    # 打开文件
    f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt')
    print(f)
    
    # read模式打开文件
    f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='r')
    # 读取文件内容,向操作系统发起读请求,会被操作系统转成具体的硬盘操作,将内容由硬盘读入内存
    data = f.read()
    print(data)
    # 由于Python的垃圾回收机制只回收引用计数为0的变量,但是打开文件还占用操作系统的资源,所以我们需要回收操作系统的资源资源
    # del f 只是回收变量f
    f.close()
    
    # write模式打开文件
    f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='w')
    f.write("""name = 'nick'
    pwd = '123'""")
    f.close()
    f = open(r'/Users/mac/desktop/jupyter/pythonCourseware/32.txt', mode='r')
    data = f.read()
    print(data)
    

    绝对路径和相对路径

    绝对路径:从盘符(C:、D:)开始写一个完整的路径。

    相对路径:相对于当前执行文件所在的文件夹开始找。

    文件的三种打开模式

    文件操作的基础模式有三种(默认的操作模式为r模式):

    • r模式为read(只读模式,只能读不能写,文件不存在时报错。)

      # rt: read by text
      # windows的操作系统默认编码为gbk,因此需要使用utf8编码
      f = open('32.txt', mode='rt', encoding='utf8')
      data = f.read()
      print(data)
      print(f"type(data): {type(data)}")
      f.close()
      

      由于f.read()一次性读取文件的所有内容,如果文件非常大的话,可能会造成内存爆掉,即电脑卡死。因此可以使用f.readline()/f.readlines()读取文件内容。

      # f.readline()/f.readlines()
      f = open('32.txt', mode='rt', encoding='utf8')
      print(f"f.readable(): {f.readable()}")  # 判断文件是否可读
      data1 = f.readline()
      data2 = f.readlines()
      print(f"data1: {data1}")
      print(f"data2: {data2}")
      f.close()
      
    • w模式为write(只能写,不能读,文件存在的时候回清空文件后再写入内容;文件不存在的时候会创建文件后写入内容。)

      # wt
      f = open('34w.txt', mode='wt', encoding='utf8')
      print(f"f.readable(): {f.readable()}")
      f.write('nick 真帅呀
      ')  # '
      '是换行符
      f.write('nick,nick, you drop, I drop.')
      f.write('nick 帅的我五体投地')
      f.flush()  # 立刻将文件内容从内存刷到硬盘
      f.close()
      
    • a模式为append(可以追加。文件存在,则在文件的末端写入内容;文件不存在的时候会创建文件后写入内容。)

      # at
      f = open('34a.txt', mode='at', encoding='utf8')
      print(f"f.readable(): {f.readable()}")
      f.write('nick 真帅呀
      ')  # '
      '是换行符
      f.write('nick,nick, you drop, I drop.')
      f.write('nick 帅的我五体投地')
      f.close()
      

    文件读写内容的格式有两种(默认的读写内容的模式为b模式):

    • t模式为text
    • b模式为bytes(b模式是通用的模式,因为所有的文件在硬盘中都是以二进制的形式存储的,需要注意的是:b模式读写文件,一定不能加上encoding参数,因为二进制无法再编码。)

    需要注意的是:t、b这两种模式均不能单独使用,都需要与r/w/a之一连用。

    with管理文件操作上下文

    之前我们使用open()方法操作文件,但是open打开文件后我们还需要手动释放文件对操作系统的占用。但是其实我们可以更方便的打开文件,即Python提供的上下文管理工具——with open()。

    with open('32.txt', 'rt', encoding='utf8') as f:
        print(f.read())
    

    with open()方法不仅提供自动释放操作系统占用的方法,并且with open可以使用逗号分隔,一次性打开多个文件,实现文件的快速拷贝。

    Copywith open('32.txt', 'rb') as fr, 
            open('35r.txt', 'wb') as fw:
        f.write(f.read())
    

    文件的高级应用

    可读、可写

    • r+t: 可读、可写
    • w+t: 可写、可读
    • a+t: 可追加、可读

    修改文件的两种方式

    方式一

    将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)。

    import os
    
    with open('37r.txt') as fr, 
            open('37r_swap.txt', 'w') as fw:
        data = fr.read()  # 全部读入内存,如果文件很大,会很卡
        data = data.replace('tank', 'tankSB')  # 在内存中完成修改
    
        fw.write(data)  # 新文件一次性写入原文件内容
    
    # 删除原文件
    os.remove('37r.txt')
    # 重命名新文件名为原文件名
    os.rename('37r_swap.txt', '37r.txt')
    

    方式二

    将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件。

    import os
    
    with open('37r.txt') as fr,
            open('37r_swap.txt', 'w') as fw:
        # 循环读取文件内容,逐行修改
        for line in fr:
            line = line.replace('jason', 'jasonSB')
            # 新文件写入原文件修改后内容
            fw.write(line)
    
    os.remove('37r.txt')
    os.rename('37r_swap.txt', '37r.txt')
    

    总而言之,修改文件内容的思路为:以读的方式打开原文件,以写的方式打开一个新的文件,把原文件的内容进行修改,然后写入新文件,之后利用os模块的方法,把原文件删除,重命名新文件为原文件名,达到以假乱真的目的。

  • 相关阅读:
    Java NIO:NIO概述
    Elasticsearch在windows上安装好了之后怎么使用?
    Elasticsearch之基本操作
    elasticsearch 第五篇(文档操作接口)
    elasticsearch 第四篇(API约定)
    elasticsearch 第三篇(安装篇)
    elasticsearch 第二篇(配置篇)
    非智能手机通信录备份并还原至Android智能手机方法
    ADB server didn't ACK 问题解决
    Samsung I9103刷cm-10.1的方法
  • 原文地址:https://www.cnblogs.com/asyouwish/p/11312149.html
Copyright © 2011-2022 走看看