zoukankan      html  css  js  c++  java
  • 第三章 Python基础——文件操作&函数

    3.1三元运算

    三元运算又称三目运算,是对简单条件的简写

    if 条件成立:
        val=1
    else:
        val=2

    改成三元运算:

    val=1 if条件成立 else 2

    3.2字符编码转换

    编码的种类情况:

     ASCLL占1个字符,只支持英文

     GB2312占2个字节,支持6700+汉字

     GBK GB2312的升级版,支持21000+汉字

     Shift-JIS日本字符

     ks_c_5601-1987韩国编码

     TIS-620泰国编码

    万国码:Unicode

    两个作用:1.支持全球的所有语言,每个国家都可以用Unicode。

         2.unicode包含了跟全球所有国家编码的映射关系。

    总之:UTF是为Unicode编码设计的一种在储存和传输时节省空间的编码方案

    注意:无论什么编码在内存里显示字符,存在硬盘里都是二进制。

    编码的转换:

    GBK中文编码←→Unicode←→Shift-JIS

    (GBK   decode到Unicode,Unicode encode到Shift-JIS    decode解码、encode编码)

    Python bytes类型

    bytes类型,即字节类型, 它把8个二进制一组称为一个byte,用16进制来表示。

    Python 2 搞了一个新的字符类型,就叫unicode类型,比如你想让你的中文在全球所有电脑上正常显示,在内存里就得把字符串存成unicode类型。

    PY3 除了把字符串的编码改成了unicode, 还把str 和bytes 做了明确区分, str 就是unicode格式的字符, bytes就是单纯二进制啦。

    3.4文件处理

    python处理文件

    例一:

    f=open(file'D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='r',encoding='utf-8')
    data=f.read()
    f.close()
    
    上边的语法解释:
    f=open(file'D:/工作日常/兼职白领学生空姐模特护士联系方式.txt' 表示文件路径
    mode='r'                                                             表示只读(可以改为其他)
    encoding=’uft-8'                                                  表示将硬盘上的0101010按照uft的规则“断句”后的每一段0101010转换成unicode的01010101,unicode对照表中有01010101和字符的对应关系。
    f.read()                                                               表示读取所有内容,内容是已经转换完毕的字符串
    
    f.close()                                                               表示关闭文件

    注意:此处的encoding必须和文件在保存时设置的编码一致,不然“断句”会不准确从而造成乱码。

    例二:

    f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='rb')
    data = f.read()
    f.close()
    
    
    上边语法解释:
    file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'      表示文件路径
    mode='rb'                                            表示只读(可以修改为其他)
    f.read()                                             表示读取所有内容,内容是硬盘上原来以某种编码保存的 010101010,即:某种编码格式的字节类型
    f.close()                                            表示关闭文件

    例一与例二的区别:在于示例2打开文件时并未指定encoding,直接以rb模式打开了文件 ,rb是指二进制模式,数据读到内存里直接是bytes格式。

    注意:

    • 文件操作时,以 “r”或“rb” 模式打开,则只能读,无法写入;
    • 硬盘上保存的文件都是某种编码的0101010,打开时需要注意:
      • rb,直接读取文件保存时原生的0101010,在Python中用字节类型表示
      • r和encoding,读取硬盘的0101010,并按照encoding指定的编码格式进行断句,再将“断句”后的每一段0101010转换成unicode的 010101010101,在Python中用字符串类型表示

    循环文件

    f=open("兼职白领学生空姐模特护士联系方式。txt",'r',encoding="uft-8")
    
    for line in f:
         print(line)
    
    f.close()

    写文件

    f.=open(file=‘D:/工作日常/兼职白领学生空姐模特护士联系方式.txt,mode='w',encoding='uft-8')
    f.write('北大本科美国留学一次50,微信号:xxxxx')
    f.close()
    
    
    上边语法解释:
    file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt  表示文件路径
    mode='w'                                             表示只写
    encoding='utf-8'                                     将要写入的unicode字符串编码成utf-8格式
    f.write(...)                                         表示写入内容,写入的内容是unicode字符串类型,内部会根据encoding转换为制定编码的 01101010101,即:字节类型
    f.close()

    二进制写

    f = open(file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt',mode='wb')
    f.write('北大本科美国留学一次50,微信号:xxxxx'.encode('utf-8'))
    f.close()
     上边语法解释:
    file='D:/工作日常/兼职白领学生空姐模特护士联系方式.txt'      表示文件路径
    mode='wb'                                             表示只以2进制模式写
    f.write(...)                                          表示写入内容,写入的内容必须字节类型,即:是某种编码格式的0101010
    f.close()

    注意:

    文件操作时,以 “w”或“wb” 模式打开,则只能写,并且在打开的同时会先将内容清空。

    写入到硬盘上时,必须是某种编码的0101010,打开时需要注意:

    • wb,写入时需要直接传入以某种编码的0100101,即:字节类型
    • w 和 encoding,写入时需要传入unicode字符串,内部会根据encoding制定的编码将unicode字符串转换为该编码的 010101010

    追加:把内容追加到文件底部

    f = open("兼职白领学生空姐模特护士联系方式.txt",'a',encoding="gbk")
    
    f.write("
    杜姗姗 北京  167 49 13324523342")
    f.close()

    注意:

    文件操作时,以 “a”或“ab” 模式打开,则只能追加,即:在原来内容的尾部追加内容

    写入到硬盘上时,必须是某种编码的0101010,打开时需要注意:

    • ab,写入时需要直接传入以某种编码的0100101,即:字节类型
    • a 和 encoding,写入时需要传入unicode字符串,内部会根据encoding制定的编码将unicode字符串转换为该编码的 010101010

    读写模式

    f = open("兼职白领学生空姐模特护士联系方式.txt",'r+',encoding="gbk")
    data = f.read() #可以读内容 
    print(data)
    f.write("
    black girl  河北  167 50  13542342233") #可以写
    f.close()

    不能添加到任意位置,W+会把之前的内容清除。

    文件操作的其他功能;

    def fileno(self, *args, **kwargs): # real signature unknown
            返回文件句柄在内核中的索引值,以后做IO多路复用时可以用到
    
        def flush(self, *args, **kwargs): # real signature unknown
            把文件从内存buffer里强制刷新到硬盘
    
        def readable(self, *args, **kwargs): # real signature unknown
            判断是否可读
    
        def readline(self, *args, **kwargs): # real signature unknown
            只读一行,遇到
     or 
    为止
    
        def seek(self, *args, **kwargs): # real signature unknown
            把操作文件的光标移到指定位置
            *注意seek的长度是按字节算的, 字符编码存每个字符所占的字节长度不一样。
            如“路飞学城” 用gbk存是2个字节一个字,用utf-8就是3个字节,因此以gbk打开时,seek(4) 就把光标切换到了“飞”和“学”两个字中间。
            但如果是utf8,seek(4)会导致,拿到了飞这个字的一部分字节,打印的话会报错,因为处理剩下的文本时发现用utf8处理不了了,因为编码对不上了。少了一个字节
    
        def seekable(self, *args, **kwargs): # real signature unknown
            判断文件是否可进行seek操作
    
        def tell(self, *args, **kwargs): # real signature unknown
            返回当前文件操作光标位置 
    
        def truncate(self, *args, **kwargs): # real signature unknown
            按指定长度截断文件
            *指定长度的话,就从文件开头开始截断指定长度,不指定长度的话,就从当前位置到文件尾部的内容全去掉。
    
        def writable(self, *args, **kwargs): # real signature unknown
            判断文件是否可写

    修改文件

    f1 = open("luffy.txt",'w',encoding="utf-8")
    
    f1.write("[路飞学城]")
    
    f1.close()
    
    f = open("luffy.txt",'r+',encoding="utf-8")
    
    f.write("alex")
    
    f.close()

    占硬盘方式的文件修改代码示例

    f_name = "兼职白领学生空姐模特护士联系方式utf8.txt"
    f_new_name = "%s.new" % f_name
    
    old_str = "乔亦菲"
    new_str = "[乔亦菲 Yifei Qiao]"
    
    f = open(f_name,'r',encoding="utf-8")
    f_new = open(f_new_name,'w',encoding="utf-8")
    
    for line in f:
    
        if old_str in line:
            new_line = line.replace(old_str,new_str)
        else:
            new_line = line
    
        f_new.write(new_line)
    
    f.close()
    f_new.close()

    上面的代码,会生成一个修改后的新文件 ,原文件不动,若想覆盖原文件

    import os
    
    f_name = "兼职白领学生空姐模特护士联系方式utf8.txt"
    f_new_name = "%s.new" % f_name
    
    old_str = "乔亦菲"
    new_str = "[乔亦菲 Yifei Qiao]"
    
    f = open(f_name,'r',encoding="utf-8")
    f_new = open(f_new_name,'w',encoding="utf-8")
    
    for line in f:
    
        if old_str in line:
            new_line = line.replace(old_str,new_str)
        else:
            new_line = line
    
        f_new.write(new_line)
    
    f.close()
    f_new.close()
    
    os.rename(f_new_name,f_name) #把新文件名字改成原文件 的名字,就把之前的覆盖掉了,windows使用os.replace # 帮助文档说明replace会覆盖原文件

    3.4函数

    函数在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C语言当中只有function,在JAVA中叫做method。

    定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

    特性:

    1.减少重复代码

    2.使程序变得可扩展

    3.使程序变得易维护

    语法定义

    def sayhi():#函数名
          print(“Hello,I‘m nobody!”)
    
    sayhi()#调用函数

    有参数的情况下

    #下边这段代码a,b=5,8
    c=a**b
    print(c)
    
    
    #改成用函数写
    def calc(x,y):
          res=x**y
          return res #返回执行函数结果
    
    c=calc(a,b) #结果赋值给C变量
    print(C)

    函数参数

    形参变量:只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

    实参:可以是常量、表达式、函数等,无论是何种类型的量,在进行函数调用时,他们都必须有确定的值,以便把这些值传给形参。因此应预先用赋值,输入等办法使参数获得确定值。

    def calc(x,y):     #x y 为形参
          res=x**y
          return res
    c=calc(a,b)         #a  b为实参
    print(c)

    默认参数

    把一个名词变成默认参数:

    def stu_register(name,age,course,country="CN")

    这样这个参数在调用时不指定,那就是默认的CN,指定的话,就是你指定的值。

    注:把CN变成默认参数后把他的位置放在最后。

    关键参数正常情况下,给函数传函数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可。指定参数名的参数就叫关键参数),但记住有一个要求就是,关键参数必须放在位置参数(以

    位置顺序确定对应关系的参数)之后。

    例如,调用时这样用

    stu_register("王山炮“,course='PY',age=22,country='JP')
    

    不可以这样用

    stu_register("王山炮“,course='PY',22,country='JP')

    更不能这样

    stu_register("王山炮“,22,age=25,country='JP')

    这样相当于两次给age赋值,会会报错。

    非固定参数

    若你的函数定义时不确定用户想传入多少个参数,就可以使用非固定函数

    def stu_register(name,age,*args):#*args会把多传入的参数变成一个元素形式
          print(name,age,args)
    
    stu-register("Alex",22)
    #输出
    #Alex 22()#后边这个()就是args,只是因为没传值,所以为空
    
    
    stu-register(“Jack”,32,“CN”,“Python")
    #输出
    #jack 32 ('CN','Python')

    还有一种**kwargs

    def stu_register(name,age,*args,**kwargs): # *kwargs 会把多传入的参数变成一个dict形式
        print(name,age,args,kwargs)
    
    stu_register("Alex",22)
    #输出
    #Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空
    
    stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
    #输出
    # Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

    返回值

    函数外边的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回。

    def stu_register(name, age, course='PY' ,country='CN'):
        print("----注册学生信息------")
        print("姓名:", name)
        print("age:", age)
        print("国籍:", country)
        print("课程:", course)
        if age > 22:
            return False
        else:
            return True
    
    registriation_status = stu_register("王山炮",22,course="PY全栈开发",country='JP')
    
    if registriation_status:
        print("注册成功")
    
    else:
        print("too old to be a student.")

    注意:

    1.函数执行过程中只要遇到return语句,就会停止执行并返回结果,那么也可以理解为return语句代表函数的结束。

    2.如果未在函数中指定return,那么函数的返回值为None

    全局与局部变量

    name="Alex Li“
    
    def change_name(name):
          print("before change:",name)
           name="金角大王,一个有的tesla的男人”
           print("after change",name)
    
    
    change_name(name)
    
    print("在外边看看name改了吗?“,naem)

    输出

    before change:ALex Li
    after change 金角大王,一个有tesla的男人
    在外边看看name改了吗?Alex Li
    name = "Alex Li"
    
    
    def change_name():
        name = "金角大王,一个有Tesla的男人"
        print("after change", name)
    
    
    change_name()
    
    print("在外面看看name改了么?", name)

    但是不能这样改:

    • 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    • 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
    • 当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。

    作用域

    作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

    在函数里修改全局变量:

    name = "Alex Li"
    
    def change_name():
        global name
        name = "Alex 又名 金角大王,路飞学城讲师"
        print("after change", name)
    
    
    change_name()
    
    print("在外面看看name改了么?", name)

    global name的作用就是要在函数里声明全局变量name ,意味着最上面的name = "Alex Li"即使不写,程序最后面的print也可以打印name

    嵌套函数

    name = "Alex"
    
    def change_name():
        name = "Alex2"
    
        def change_name2():
            name = "Alex3"
            print("第3层打印", name)
    
        change_name2()  # 调用内层函数
        print("第2层打印", name)
    
    
    change_name()
    print("最外层打印", name)

    输出

    第3层打印 Alex3
    第2层打印 Alex2
    最外层打印 Alex

    匿名函数

    匿名函数就是不需要显示的制定函数名

    #这段代码
    def calc(x,y):
        return x**y
    
    print(calc(2,5))
    
    #换成匿名函数
    calc = lambda x,y:x**y
    print(calc(2,5))

    高阶函数

    变量可以指向函数,函数的参数可以接受变量,那么一个函数就可以接受另一个函数作为参数,这种函数称之为高阶函数。

    def add(x,y,f):
        return f(x) + f(y)
    
    
    res = add(3,-6,abs)
    print(res)

    只需满足一下任意一个条件就是高阶函数

    接受一个或多个函数作为输入

    return返回另外一个函数

    递归

    在函数内部,可以调用其他函数。如果一个函数的内部调用自身本身,这个函数就是递归函数。

    def calc(n):
        print(n)
        if int(n/2) ==0:
            return n
        return calc(int(n/2))
    
    calc(10)

    输出

    10
    5
    2
    1

    递归特性:

    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

    内置函数

    几个古怪内置方法的提醒

    #compile
    f = open("函数递归.py")
    data =compile(f.read(),'','exec')
    exec(data)
    
    
    #print
    msg = "又回到最初的起点"
    f = open("tofile","w")
    print(msg,"记忆中你青涩的脸",sep="|",end="",file=f)
    
    
    # #slice
    # a = range(20)
    # pattern = slice(3,8,2)
    # for i in a[pattern]: #等于a[3:8:2]
    #     print(i)
    #
    #
    
    
    #memoryview
    #usage:
    #>>> memoryview(b'abcd')
    #<memory at 0x104069648>
    #在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存,
    import time
    for n in (100000, 200000, 300000, 400000):
        data = b'x'*n
        start = time.time()
        b = data
        while b:
            b = b[1:]
        print('bytes', n, time.time()-start)
    
    for n in (100000, 200000, 300000, 400000):
        data = b'x'*n
        start = time.time()
        b = memoryview(data)
        while b:
            b = b[1:]
        print('memoryview', n, time.time()-start)
  • 相关阅读:
    【C语言篇】☞ 2. 常量、变量、scanf函数和printf 函数
    【C语言篇】☞ 1. 前言、基础
    React快速入门教程
    数论-欧拉函数
    数论-约数
    数论-质数专题
    匈牙利算法求二分图的最大匹配数
    染色法判断二分图
    Kruskal算法
    Prim算法
  • 原文地址:https://www.cnblogs.com/cnlogs1/p/9549960.html
Copyright © 2011-2022 走看看