python字符编码、文件处理、函数

一、字符编码


  1、什么是字符编码
    把字符转换成计算机可识别的机器码(0,1)的过程,称之为字符编码。


  2、字符编码的类型

    1)现代计算机起源于美国,最早诞生也是基于英文考虑的ASCII
      ASCII:一个Bytes(字节)代表一个字符(英文字符、键盘上的所有其它字符),1Bytes=8bit,8bit可以表示为2的8次方种变化,即可以表示256个字符。
      ASCII最初只用了后攻位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符),后期将拉丁文也编码进了ASCII表,占用了最高位。
    2)为了满足中文,中国人定制了GBK
      GBK:2Bytes代表一个字符
      为了满足需求,各国家分别定制了自己的编码。日文编码Shift_JIS,韩文编码Euc-kr。
    3)各国编码遵循自己的标准,当在多语言混合的文本中,就会出现冲突,显示乱码。于是产生了unicode万国码。
      unicode:至少用2Bytes代表一个字符,2**16-1=65535,可代表655535个字符,因而兼容万国语言。
      由于至少使用2字节代表一个字符,对于英文文本来说,多占用了一倍的存储空间,于是产生了utf-8。    
    4)utf-8:对文本进行判断,中文使用3Bytes,英文字符只有1Bytes。
      ps:unicode与uft-8比较:
      unicode:简单粗暴,所有字符都是2Bytes,优点是字符->数字的转换速度快,缺点是占用空间大。(内存使用unicode速度快)
      utf-8:精准,对不同的字符用不同的长度表示,优点是节省空间,缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示。(硬盘使用utf-8节省空间)


  3、字符编码的使用
    以文本编辑器举例,不管时打开读取还是修改都是在内存中打开。
    读取文件时,是decode的过程:把硬盘中utf-8格式的文本-》decode(翻译)-》内存unicode格式
    保存文件时,是encode的过程:把内存中unicode格式的文本-》encode(翻译)-》硬盘中utf-8格式


  4、python3与2中编码的区别

    python3中所有的字符串都会被识别成unicode 字符编码。
    python2中所有的字符串就是编码后的结果bytes字节。

二、文件处理


  1、打开文件的两种方式:
    1)open函数打开文件后需要close关闭

      f = open('a.txt','r',encodeing='utf-8')
      data = f.read()
      print(data)
      f.close()

    2)with open打开文件后不需要关闭,使用with命令换行会自动缩进,缩进里的代码都是对文件的操作,退出缩进会自动关闭文件。

     with open('a.txt','r',encoding='utf-8') as f:
     data = f.read()
     print(data)

  2、文件操作模式:
    open与with参数都一样。
    参数一:a.txt,文件名,相对路径或绝对路径均可。
    参数二:'r',操作模式,
      r 只读,默认,文件不存在则报错,存在则读取,。
      w 只写,不可读,文件不存在则创建,存在则写入(会先清空再写入),。
      x 只写,不可读,文件不存在则创建,存在则报错。
      a 追加,可读,不存在则创建 ,存在则只追加内容。
    "+"表示可以同时读写某个文件
      r+ 读写
      w+ 写读
      x+ 写读
      a+ 写读
    "b"表示以字节的方式操作
      rb 或 r+b
      wb 或 w+b
      xb 或 x+b
      ab 或 a+b
    注:以b方式打开时,读取到的内容是了节类型,写入时也需要提供字节类型。
    参数三:encodeing='utf-8',指定字符编码。

  3、文件读取操作
    1)读取文件,以读r的方式打开文件,有则清空,无则报错
      f1 = open('a.txt',encoding='utf-8')
      data = f1.read()
      print(data)
    2)读取文件,输出两次时,默认第二次输出为空。
      因为读取是光标逐行读取的,第一次读取后光标会走到文件最后。
      如果第二次想要打印出文件内容,需要使用seek将光标重新定位一文件开始位置。
      f1 = open('a.txt','r', encoding='utf-8')
      print(f1) #查看读取属性
      print(f1.read())
      f1.seek(0)
      print(f1.read())

    3)判断文件是否可读 (true false)
      f1 = open('a.txt','r', encoding='utf-8')
      data = f1.readable()
      print(data)
      f1.close()
    4)逐行读取文件(不能把文件赋值),默认会打印换行符,使用end=''替换print自带的换行符为空
      f1 = open('a.txt','r', encoding='utf-8')
      print(f1.readline())
      print(f1.readline(),end='')
      print(f1.readline())
      f1.close()
    5)以列表形式显示文件
      f1 = open('a.txt','r', encoding='utf-8')
      print(f1.readlines())
      f1.close()

  4、文件写入操作
    1)写文件,以写w的方式打开文件,有则清空,无则创建
      逻辑为先清空内容,再写入,不重建文件,且不会修改文件创建时间,只更新修改时间
      f1 = open('a.txt','w', encoding='utf-8')
    2)判断文件是否可写 (true false)
      f1 = open('a.txt','w', encoding='utf-8')
      print(f1.writable())
    3)写入文件内容
      f1 = open('a.txt','w', encoding='utf-8')
      f1.write('111 222 333')
      f1.write(' 444 555 666')
      f1.close
    4)以列表格式写入文件内容
      f1 = open('a.txt','w', encoding='utf-8')
      f1.writelines(['111','222','333'])
      f1.close
    5)追加文件内容
      f1 = open('a.txt','a', encoding='utf-8')
      f1.write('777 888 999')
      f1.close)
    6)模拟文件修改,判断修改文件,循环文件,判断,逐条写入文件2,遇到匹配进行修改并写入修改后的内容,最后使用os模块覆盖原文件
      import os #导入os模块
      read_f = open('a.txt','r', encoding='utf-8')
      write_f = open('a.txt.swap','w', encoding='utf-8')
      for line in read_f.readlines(): #循环显示文件列表
        if line.startswith('111'): #判断如果以‘111’开头
          line='999 ' #修改111为999
        write_f.write(line) #读取一条写入到.swap文件,如匹配判断条件,则写入修改后的内容
      read_f.close()
      write_f.close()
      #覆盖原文件
      os.remove('a.txt') #删除原文件
      os.rename('a.txt.swap','a.txt') #重命名文件a.txt.swap为a.txt


  5、bytes模式操作文件
    以bytest模式操作文件时,读取时显示为二进制,并且只能写入二进制。
    1)以bytes模式读取文件,显示二进制
      with open('a.txt','rb') as f:
        print(f.read())
    2)以bytes模式写入文件,需要加encode
      with open('a.txt','wb') as f:
        f.write('牛牛牛'.encode('utf-8'))
    3)bytes模式常用环境
      文本的方式读不了二进制文件,硬盘上存储的都是二进制数据,除了文本之外,其它的都需要以二进制方式打开如.jpg格式。
      with open('zly.jpg','rb') as read_f,open('zly_new.jpg','wb') as write_f:
        data = read_f.read()
        write_f.write(data)

三、补充
  1、三元表达式
    三元表达式(精简),条件成立写左边x,不成立写右边y
    正常写法:
      x = 10
      y = 2
      if x > y:
      print(x)
      else:
      print(y)
    三元表达式:result = 值1 条件 值2,如果条件成立,那么将 “值1” 赋值给result变量,否则,将“值2”赋值给result变量
      result = x if x > y else y
      print(result)

  2、文件内光标移动*
    注意:read(3)代表读取3个字符,其余的文件内光标移动都是以字节为单位如seek,tell,read,truncate
    1)read()
      with open('a.txt','r',encoding='utf-8') as f:
        print(f.read(3))
    2)seek() 参数一是位移值指从开始第第几个字符,参数二是起始位置包含0、1、2三个值,0表示文件起始位置,1表示当前位置,2表示文件结尾位置(1和2常用于rb模式)
      with open('a.txt','r',encoding='utf-8') as f:
        f.seek(0) #将光标移动到文件起始位置。
        f.seek(3) #默认情况,是以文件起始位置作为开始,往后移动3个bytes,#当前光标在第三个字节后,打印就会打印第三个字节后的内容
        f.seek(2,1) #1 代表以当前光标所在的位置为开始,往后移动2个 bytes
        f.seek(-1,2) # 2表以文件结尾位置为开始,往回移动1个 bytes, 都算一个bytes

    3)tell() ,显示当前所在的字节位置,打印3
      with open('a.txt','r',encoding='utf-8') as f:
        f.seek(3)
        print(f.tell())

    4)truncate() 截断,truncate内指定的数字代表字节,指保留从开始到指定数字。写入操作,打开文件时需要用r+ 。
      a.txt 你瞅啥 #一个汉字代表三个字节,打印前6个字节,最终结果显示 你瞅
      with open('a.txt','r+',encoding='utf-8') as f:
        f.truncate(6)

  3、for循环返回值
    对for循环执行成功后的返回值提示,如遇到break则不会执行。
    with open('a.txt','r',encoding='utf-8') as f:
      for i in f:
        print(i)
        #break
      else:
        print("执行成功!")

四、函数
  1、函数的特点
    1)可读性高
    2)统一管理且维护成本低
    3)有组织有结构,一次定义多次调用

  2、函数的分类
    1)内置函数
      内置函数是内置在python中的,可以直接调用。
      如:sum、max、min、len等。
        b = sum([1,2])
        print(b)
    2)自定义函数
      为什么要定义函数?:先定义后使用,如果没有定义而直接使用,就相当于引用了一个不存在的变量名
      def foo():
        print('from foo')
      print(foo)

      函数的使用包含两个阶段:定义阶段和使用阶段

        语法
        def 函数名(参数1,参数2,...):
          """文档注释"""
          函数体
          return 值

        x=len('hello')
        print(x)

      函数的定义主要有如下要点:
        def:表示函数的关键字
        函数名:函数的名称,日后根据函数名调用函数
        函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
        参数:为函数体提供数据
        返回值:当函数执行完毕后,可以给调用者返回数据。

      自定义函数例:
        def print_star(): #定义函数
          print('*'*6) #函数体

        def print_msg():
          print('hello world')
      调用:
        print_star() #调用函数
        print_star()
        print_msg() #调用函数
        print_star()
        print_star()

      结果:
        ******
        ******
        hello world
        ******
        ******

  3、定义函数的形式以及调用函数
    1)无参,如果函数的功能仅仅只是执行一些操作而已,就定义成无参函数,无参函数通常都有返回值,
      def print_star():
        print('#'*6)

    2)有参函数:函数的功能的执行依赖于外部传入的参数,有参函数通常都有返回值
      def my_max(x,y):
        res=x if x >y else y
        return res
    3)调用函数,按照有参和无参可以将函数调用分两种
      def foo():
        print('from foo')

      def bar(name):
        print('bar===>',name)

      foo() #定义时无参,调用时也无需传入参数
      bar('egon') #定义时有参,调用时也必须有参数

    4)按照函数的调用形式和出现的位置分三种
      (1)调用函数的语句形式
        def foo():
          print('from foo')
        foo()
      (2)调用函数的表达式形式,xy传参乘以10000000
        def my_max(x,y):
          res=x if x >y else y
          return res

        res=my_max(1,2)*10000000
        print(res)
      (3)把函数调用当中另外一个函数的参数
        def my_max(x,y):
          res=x if x >y else y
          return res
        res=my_max(my_max(10,20),30)
        print(res)


  4、函数的返回值
    1)三种情况返回值都为None:
      没有return
      return 什么都不写
      return None
    2)return 一个值 函数调用返回的结果就是这个值
      def foo():
        print('from foo')
        x=1
        return x
      res=foo()
      print(res)
    3)return 值1,值2,值3,... 返回结果:(值1,值2,值3,...)
      def foo():
        print('from foo')
        x=1
        return 1,[2,3],(4,5),{}
      res=foo()
      print(res) #打印结果:(1,[2,3],(4,5),{})
      a,b,c,d=foo()
      print(d)
    4)序列的解压
        t=(1,2,3)
        a,b,c=t
        print(a) #打印1
        print(b) #打印2
        print(c) #打印3
      只要第一个值,其它值使用_下划线占位
        t=(1,2,3)
        a,_,_=t
        print(a) #只打印a的值1

      只要开头和结尾的值,中间使用*_占位中间所有参数
        t=(1,2,3,4,5,6)
        a,*_,c=t
        print(a,c) #只打印开头和结尾的值,执行结果打印 1 6


  5、函数的参数
    1)形参(变量名),实参(值)。
      x和y为形参(变量名),1和2为实参(值),最后执行结果打印1 2 。
      #定义阶段
        def foo(x,y): #x=1,y=2
          print(x)
          print(y)
      #调用阶段
        foo(1,2)


      详细的区分函数的参数分为五种:
      位置参数,关键字参数,默认参数,可变长参数(*args,**kwargs),命名关键字参数
    2)位置参数
      def foo(x,y,z):#位置形参:必须被传值的参数
        print(x,y,z)

      foo(1,2,3) #位置实参数:与形参一一对应

    3)关键字参数:key=value
      def foo(x,y,z):
        print(x,y,z)

      foo(z=3,x=1,y=2)

      关键字参数需要注意的问题:
        1:关键字实参必须在位置实参后面
        2: 不能重复对一个形参数传值
          foo(1,z=3,y=2) #正确
          foo(x=1,2,z=3) #错误


    4)默认参数
        def register(name,age,sex='male'): #形参:默认参数
          print(name,age,sex)
        register('asb',age=40)
      默认参数需要注意的问题:
        (1)默认参数必须跟在非默认参数后,否则在定义阶段就会报错
          def register(sex='male',name,age): #在定义阶段就会报错
            print(name,age,sex)

        (2):默认参数在定义阶段就已经赋值了,而且只在定义阶段赋值一次,最终foo(1)结果为100000000。
          a=100000000
          def foo(x,y=a):
            print(x,y)
          a=0
          foo(1)
        (3)默认参数的值通常定义成不可变类型(如元组)。

    5)可变长参数
      (1)*args,*会把溢出的按位置定义的实参都接收,以元组的形式赋值给args
        def foo(x,y,*args):
          print(x,y)
          print(args)
        foo(1,2,3,4,5)
        循环计算溢出参数:
        def add(*args):
          res=0
          for i in args:
            res+=i
          return res
        print(add(1,2,3,4))
        print(add(1,2))
      (2)**kwargs,**会把溢出的按关键字定义的实参都接收,以字典的形式赋值给kwargs
        def foo(x, y, **kwargs):
          print(x, y)
          print(kwargs)
        foo(1,2,a=1,name='egon',age=18)
        判断如果溢出参数中有if的条件,则打印实参,最后调用函数。

        def foo(name,age,**kwargs):
          print(name,age)
          if 'sex' in kwargs:
            print(kwargs['sex'])
          if 'height' in kwargs:
            print(kwargs['height'])

        foo('egon',18,sex='male',height='185')
        foo('egon',18,sex='male')

    6)命名关键字参数,*后定义的参数为命名关键字参数,这类参数,必须被传值,而且必须以关键字实参的形式去传值
      def foo(name,age,*,sex='male',height):
        print(name,age)
        print(sex)
        print(height)
      foo('egon',17,height='185')
    7) 补充:函数定义阶段到底干了什么事情:只检测函数体的语法,并不会执行
      def bar():
        x
        if 1 >2:
        print('====>')
      #bar()




 





 

原文地址:https://www.cnblogs.com/zhangmeixia/p/6857448.html