• python学习 day3


    一、python文件操作

    文件操作基本流程:

    计算机系统分为:计算机硬件,操作系统,应用程序三部分。

    我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所周知,应用程序是无法直接操作硬件的,这就用到了操作系统。操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,其中文件就是操作系统提供给应用程序来操作硬盘虚拟概念,用户或应用程序通过操作文件,可以将自己的数据永久保存下来。

    有了文件的概念,我们无需再去考虑操作硬盘的细节,只需要关注操作文件的流程:

    方法一:
    #打开文件,得到文件句柄并赋值给一个变量
    f = open('D:code\1.txt',encoding='utf-8',mode='r')  #指定打开文件的自己,默认是以读模式打开
    file = f.read()  #通过句柄对文件进行操作
    
    f.close()   #关闭文件,使用该方法打开的文件,操作完成一定要进行关闭,不然会有内存溢出的风险
    
    方法二:
    #次方法的优点不需要担心关闭文件,只要在with语句下的代码执行完毕后,该方法会自动帮你将文件关闭
    with open('D:codest.txt','w') as f:
         f.write("hello")    #绝对路径

    文件打开方式:

    #1. 打开文件的模式有(默认为文本模式):
    r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
    w,只写模式【不可读;不存在则创建;存在则清空内容】
    a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】
    注:正常工作中使用r、w、a这三种模式就完全够用了,不建议使用r+、w+等模式
    
    #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
    rb 
    wb
    ab
    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
    
    #3,‘+’模式(就是增加了一个功能)
    r+, 读写【可读,可写】
    w+,写读【可写,可读】
    a+, 写读【可写,可读】
    
    #4,以bytes类型操作的读写,写读,写读模式
    r+b, 读写【可读,可写】
    w+b,写读【可写,可读】
    a+b, 写读【可写,可读】

    常用的文件操作方法:

    f1 = open('空姐护士老师主妇.txt', encoding='utf-8', mode='r')
    content = f1.read()
    print(content)
    f1.close()
    
    # read 全部读出,强烈不建议使用该方法,因为该方法会将全部文件都加载到内存中,如果文件过大的话会撑爆内存
    f1 = open('log1', encoding='utf-8')
    content = f1.read()  #
    print(content)
    f1.close()
    
    #read(n)
    f1 = open('log1', encoding='utf-8')
    content = f1.read(5)  # r 模式 按照字符读取。
    print(content)
    f1.close()
    
    f1 = open('log1', mode='rb')
    content = f1.read(3)  # rb模式 按照字节读取。
    print(content.decode('utf-8'))
    f1.close()
    
    #readline()按行读取
    f1 = open('log1', encoding='utf-8')
    print(f1.readline())
    print(f1.readline())
    print(f1.readline())
    print(f1.readline())
    f1.close()
    
    #readlines() 将每一行作为列表的一个元素并返回这个列表
    f1 = open('log1', encoding='utf-8')
    print(f1.readlines())
    f1.close()
    
    #for循环
    f1 = open('log1', encoding='utf-8')
    for i in f1:
        print(i)
    f1.close()
    
    #我们在工作建议使用for循环的方法
    
    #编码的补充:
    s1 = b'xd6xd0xb9xfa'
    s2 = s1.decode('gbk')
    s3 = s2.encode('utf-8')
    #将gbk编码转换为utf-8
    print(s3)  # b'xe4xb8xadxe5x9bxbd'
    s1 = b'xd6xd0xb9xfa'.decode('gbk').encode('utf-8')
    print(s1)

    文件修改:

    1,打开原文件,产生文件句柄。
    2,创建新文件,产生文件句柄。
    3,读取原文件,进行修改,写入新文件。
    4,将原文件删除。
    5,新文件重命名原文件。

    #文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:
    
    方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)
    import os  # 调用系统模块
    
    with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
        data=read_f.read() #全部读入内存,如果文件很大,会很卡
        data=data.replace('Tom','jerry') #在内存中完成修改
    
        write_f.write(data) #一次性写入新文件
    
    os.remove('a.txt')  #删除原文件
    os.rename('.a.txt.swap','a.txt')   #将新建的文件重命名为原文件
    
    方法二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件
    import os
    
    with open('a.txt') as read_f,open('.a.txt.swap','w') as write_f:
        for line in read_f:
            line=line.replace('Tom','jerry')
            write_f.write(line)
    
    os.remove('a.txt')
    os.rename('.a.txt.swap','a.txt') 

    二、函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print(),len()等。但你也可以自己创建函数,这被叫做用户自定义函数。

    #函数定义
    def mylen():
        """计算s1的长度"""
        s1 = "hello world"
        length = 0
        for i in s1:
            length = length+1
        print(length)
    
    #函数调用  
    mylen() #函数名+() 执行函数
    
    #函数的返回值 return
    '''
    1,遇到return,结束函数。
    def func1():
    print(11)
    print(22)
    return
    print(333)
    print(444)
    func1()
    2,给函数的调用者(执行者)返回值。
    无 return 返回None
    return 不写 或者 None 返回None
    return 返回单个数.
    return 返回多个数,将多个数放在元组中返回。
    '''

    函数参数:

    #函数定义
    def mylen(s1):
        """计算s1的长度"""
        length = 0
        for i in s1:
            length = length+1
        return length
    
    #函数调用
    str_len = mylen("hello world")
    print('str_len : %s'%str_len)

    我们告诉mylen函数要计算的字符串是谁,这个过程就叫做 传递参数,简称传参,我们调用函数时传递的这个“hello world”和定义函数时的s1就是参数

    实参与形参

    参数还有分别:

    我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。

    定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。 

    传递多个参数

    参数可以传递多个,多个参数之间用逗号分割。

    def mymax(x,y):
        the_max = x if x > y else y
        return the_max
    
    ma = mymax(10,20)
    print(ma)

    动态参数 *args,**kwargs 万能参数

    三、命名空间和作用域

    我们回忆一下python代码运行的时候遇到函数是怎么做的。

    从python解释器开始执行之后,就在内存中开辟了一个空间

    每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。

    但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。

    等执行到函数调用的时候,python解释器会再开辟一块内存来存储这个函数里的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    注:我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间

     代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间

    命名空间与作用域:

    命名空间一共分为三种:

      全局命名空间

      局部命名空间

      内置命名空间

    *内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

    三种命名空间之间的加载与取值顺序:

    加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

    取值:

      在局部调用:局部命名空间->全局命名空间->内置命名空间

    作用域

    作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

    局部作用域:局部名称空间,只能在局部范围生效

    globals和locals方法

    def func():
        a = 12
        b = 20
        print(locals())
        print(globals())
    
    func()

    输出:

    {'b': 20, 'a': 12}
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0578A590>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/Python/day4/练习.py', '__cached__': None, 'func': <function func at 0x0582B8E8>}

     

    闭包

    def func():
        name = 'eva'
        def inner():
            print(name)

    闭包函数:

    内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数
    #函数内部定义的函数称为内部函数

    判断闭包函数的方法__closure__

    #输出的__closure__有cell元素 :是闭包函数
    def func():
        name = 'eva'
        def inner():
            print(name)
        print(inner.__closure__)
        return inner
    
    f = func()
    f()
    
    #输出的__closure__为None :不是闭包函数
    name = 'egon'
    def func2():
        def inner():
            print(name)
        print(inner.__closure__)
        return inner
    
    f2 = func2()
    f2()

    总结:

    命名空间:

      一共有三种命名空间从大范围到小范围的顺序:内置命名空间、全局命名空间、局部命名空间

    作用域(包括函数的作用域链):

    小范围的可以用大范围的
    但是大范围的不能用小范围的
    范围从大到小(图)

    在小范围内,如果要用一个变量,是当前这个小范围有的,就用自己的
    如果在小范围内没有,就用上一级的,上一级没有就用上上一级的,以此类推。
    如果都没有,报错

    函数的嵌套:

      嵌套调用

      嵌套定义:定义在内部的函数无法直接在全局被调用

    函数名的本质:

      就是一个变量,保存了函数所在的内存地址

    闭包:

      内部函数包含对外部作用域而非全剧作用域名字的引用,该内部函数称为闭包函数

     

  • 相关阅读:
    Linux远程连接Windows桌面
    Ubuntu telnet
    Linux Source命令及脚本的执行方式解析(转)
    Java图形与文本(18)
    从把3000行代码重构成15行代码谈起
    学习:java原理—反射机制
    BugFix系列---开篇介绍
    回调函数透彻理解Java
    Java回调函数的理解
    Java注解浅谈
  • 原文地址:https://www.cnblogs.com/watchslowly/p/8934381.html
Copyright © 2020-2023  润新知