3.28 python文件操作及函数 学习笔记

1 文件操作

1)打开文件

​ file = open(‘文件位置’, encoding=‘utf-8’, mode=‘r’) # 内置函数,open底层调用的是操作系统的接口

​ 参数: file 文件名变量, 文件句柄

​ ‘文件所在位置’

​ encoding:可以不写,不写参数默认编码本:操作系统默认的编码

​ windows: gbk linux: utf-8 mac: utf-8

2)读文件

读取方式:r, rb, r+, r+b四种模式都有以下方法

:rb:操作非文本文件,如:图片、视频、音频(二进制文件)

​ r+:读写,读并追加,不会创建新文件和自动换行

当文件比较小时:

​ file.read() # 读取全部内容

​ file.read(n) # 读取前n个字符

​ file.readline() # 读取一行

​ file.readlines() # 返回一个列表,列表中的每个元素是所读文件的每一行(包含每一行的换行符)

当文件比较大时:

​ for读取: 每次只读取一行,不占用内存

f1= open('test.txt', encoding="gbk", mode='r')
for line in f1:
    print(line)
f1.close()

3)写文件

写入模式:w, wb, w+, w+b 四种模式

​ file.write(内容) # 没文件创建文件写入内容,文件存在,先清空原文件内容,在写入新内容

4) 文件追加

追加模式:a, ab, a+, a+b 四种模式

​ file.write(内容) # 文件不存在创建文件追加写入内容,文件存在,直接追加写入新内容(不自动换行)

5)其他

​ file.tell() # 光标的位置,单位:字节

​ file.seek() # 调整光标的位置

​ file.flush() # 强制刷新(保存)

6)打开文件的另一种方式

优点1:不用手动关闭文件

​ with open(文件位置, encoding=“utf-8”) as file:

​ file.操作方法

优点2:可以同时打开多个文件

​ with open(文件位置, encoding=“utf-8”) as file1, open(文件位置, encoding=“utf-8”) as file2:

​ file1.操作方法

​ file2.操作方法

7)改文件

'''
1, 以读的模式打开原文件。
2,以写的模式创建一个新文件。
3,将原文件的内容读出来修改成新内容,写入新文件。
4,将原文件删除。
5,将新文件重命名成原文件。
'''
# low版
import os
# # 1, 以读的模式打开原文件。
# # 2,以写的模式创建一个新文件。
with open('alex自述',encoding='utf-8') as f1,\
    open('alex自述.bak',encoding='utf-8',mode='w') as f2:
# # 3,将原文件的内容读出来修改成新内容,写入新文件。
    old_content = f1.read()
    new_content = old_content.replace('alex', 'SB')
    f2.write(new_content)
os.remove('alex自述')
os.rename('alex自述.bak','alex自述')


# 进阶版:
import os
# 1, 以读的模式打开原文件。
# 2,以写的模式创建一个新文件。
with open('alex自述',encoding='utf-8') as f1,\
    open('alex自述.bak',encoding='utf-8',mode='w') as f2:
# 3,将原文件的内容读出来修改成新内容,写入新文件。
    for line in f1:
        # 第一次循环 SB是老男孩python发起人,创建人。
        new_line = line.replace('SB', 'alex')
        f2.write(new_line)
os.remove('alex自述')
os.rename('alex自述.bak','alex自述')



# 有关清空的问题:
# 关闭文件句柄,再次以w模式打开此文件时,才会清空。
with open('文件的写', encoding='utf-8',mode='w') as f1:
    for i in range(9):
        f1.write('恢复贷款首付款')

8)读取方式详解

  • 读取方式

    • ‘r’只读。该文件必须已存在。
    • ‘r+’可读可写。该文件必须已存在,写为追加在文件内容末尾。
    • ‘rb’:表示以二进制方式读取文件。该文件必须已存在。
    • ‘w’只写。打开即默认创建一个新文件,如果文件已存在,则覆盖写(即文件内原始数据会被新写入的数据清空覆盖)。
    • ‘w+’写读。打开创建新文件并写入数据,如果文件已存在,则覆盖写。
    • ‘wb’:表示以二进制写方式打开,只能写文件, 如果文件不存在,创建该文件;如果文件已存在,则覆盖写。
    • ‘a’追加写。若打开的是已有文件则直接对已有文件操作,若打开文件不存在则创建新文件,只能执行写(追加在后面),不能读。
    • ‘a+’追加读写。打开文件方式与写入方式和’a’一样,但是可以读。需注意的是你若刚用‘a+’打开一个文件,一般不能直接读取,因为此时光标已经是文件末尾,除非你把光标移动到初始位置或任意非末尾的位置。(seek()方法解决光标问题, )
  • 光标移动问题

    • 语法:fileObject.seek(offset[, whence])

    • 参数:

      • offset – 开始的偏移量,也就是代表需要移动偏移的字节数,如果是负数表示从倒数第几位开始。
      • **whence:**可选,默认值为 0。给 offset 定义一个参数,表示要从哪个位置开始偏移;0 代表从文件开头开始算起,1 代表从当前位置开始算起,2 代表从文件末尾算起。
    • 返回值:如果操作成功,则返回新的文件位置,如果操作失败,则函数返回 -1。

    • eg:

      # 打开文件
      f = open("test.txt", "r+")
      print ("文件名为: ", f.name)
      
      # 读取完文件后光标移动到文件末尾 
      line = f.readline()
      print (f'读取的数据为: {line}')
       
      # 重新设置文件读取光标到开头
      f.seek(0, 0)
      line = f.readline()
      print (f'读取的数据为: {line}')
       
      # 关闭文件
      f.close()
      

2 函数

1)万能参数

*args 常称:args

​ 函数定义时,*代表聚合。她将所有的位置参数聚合成一个数组,赋值给了args

位置:放在关键字参数前

​ **kwargs

​ 函数的定义时,**将所有的关键字参数聚合到一个字典中,将这个字典赋值给了kwargs

位置:放在关键字参数后

形参角度的最终顺序:位置参数、*args、默认参数、仅限关键字参数、**kwargs

​ * **在函数的调用中,代表打散;在函数的定义中代表聚合

2)命名空间

​ 在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.

我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。

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

我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间

代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间

在函数的运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间

python还有一个空间叫做内置名称空间:内置名称空间存放的就是一些内置函数等拿来即用的特殊的变量:input,print,list等等

在这里插入图片描述

内置函数

	* globals()  # 返回的是字典:字典里面的键值对是全局作用域的所有内容
	* locals()  # 返回的是字典:字典里面的键值对是局部作用域的所有内容

关键字:nonlocal global

3)函数陷阱

陷阱一:

​ 如果你的默认参数指向的是可变的数据类型,那么你无论调用多少次这个默认参数,都是同一个对象。

def func(a, list=[]):
    list.append(a)
    return list
print(func(10,))  # [10,]
print(func(20,[]))  # [20,],传入新的list则不是用原来命名空间内的list
print(func(100,))  # [10,100],直接会内部命名空间的list

陷阱二:

​ 局部作用域的陷阱:

count = 1
def func():
	print(count)
	count = 3
func()

# 报错,因为print(count)时,python会先在函数内部所有范围内找,发现变量引用在定义之前,直接报错
# python在这里并不会找到全局变量

4)global、nonlocal

  • global:

    1.在局部作用域内声明一个全局变量;

    name = 'alex'
    
    def func():
        global name
        name = '太白金星'
        # print(name)
    func()
    print(name)
    

    2.在函数内部修改全局变量

    count = 1
    def func():
        # print(count)
        global count
        count += 1
    print(count)
    func()
    print(count)
    
  • nonlocal:

    1.不能够操作全局变量;

    count = 1
    def func():
        nonlocal count  # 报错
        count += 1
    func()
    

    2.局部作用域:内层函数对外层函数的局部变量进行修改

def wrapper():
    count = 1
    def inner():
        nonlocal count
        count += 1
    print(count)
    inner()
    print(count)
wrapper()

6)函数名

  • 函数名指的就是函数的内存地址
  • 函数名就是变量
  • 函数名可以当做容器类数据类型(list、tuple、dict、set)的元素
  • 函数名可以作为函数的参数、
  • 函数名可以作为函数的返回值

7)新特性:格式化输出

类似format

# %s format
name = '太白'
age = 18
msg = '我叫%s,今年%s' %(name,age)
msg1 = '我叫{},今年{}'.format(name,age)

# 新特性:格式化输出
name = '太白'
age = 18
msg = f'我叫{name},今年{age}'
print(msg)

# 可以加表达式
dic = {'name':'alex','age': 73}
msg = f'我叫{dic["name"]},今年{dic["age"]}'
print(msg)

# count = 7
print(f'最终结果:{count**2}')
name = 'barry'
msg = f'我的名字是{name.upper()}'
print(msg)

# 结合函数写:
def _sum(a,b):
    return a + b

msg = f'最终的结果是:{_sum(10,20)}'
print(msg)
# ! , : { } ;这些标点不能出现在{} 这里面。
# 优点:
#  1. 结构更加简化。
#  2. 可以结合表达式,函数进行使用。
# 3. 效率提升很多。

8)迭代器

  • 可迭代对象

    字面意思:对象?python中一切皆对象。一个实实在在存在的值,对象。

    可迭代?:更新迭代。重复的,循环的一个过程,更新迭代每次都有新的内容,

    可以进行循环更新的一个实实在在值。

    专业角度:可迭代对象? 内部含有'__iter__'方法的对象,可迭代对象。

    目前学过的可迭代对象?str list tuple dict set range 文件句柄

  • 获取对象的所有方法并且以字符串的形式表现:dir()

  • 判断一个对象是否是可迭代对象

    s1 = 'fjdskl'
    # l1 = [1,2,3]
    # # print(dir(s1))
    # print(dir((l1)))
    # print('__iter__' in dir(s1))
    # print('__iter__' in dir(range(10)))
    
  • 小结

    • 字面意思:可以进行循环更新的一个实实在在值。

    • 专业角度: 内部含有'__iter__'方法的对象,可迭代对象。

    • 判断一个对象是不是可迭代对象: '__iter__' in dir(对象)

    • str list tuple dict set range

    • 优点

      1. 存储的数据直接能显示,比较直观。
      2. 拥有的方法比较多,操作方便。
    • 缺点

      1. 占用内存。

      2. 不能直接通过for循环,不能直接取值(索引,key)。

  • 迭代器

  • 迭代器的定义

    • 字面意思:更新迭代,器:工具:可更新迭代的工具。
    • 专业角度:内部含有'__iter__'方法并且含有'__next__'方法的对象就是迭代器。
    • 可以判断是否是迭代器:'__iter__' and '__next__' 在不在dir(对象)
  • 判断一个对象是否是迭代器

    with open('文件1',encoding='utf-8',mode='w') as f1:
        print(('__iter__' in dir(f1)) and ('__next__' in dir(f1)))
    
  • 迭代器的取值

    s1 = 'fjdag'
    obj = iter(s1)  # s1.__iter__()
    # print(obj)
    # print(next(obj)) # print(obj.__next__())
    # print(next(obj)) # print(obj.__next__())
    # print(next(obj)) # print(obj.__next__())
    # print(next(obj)) # print(obj.__next__())
    # print(next(obj)) # print(obj.__next__())
    # print(next(obj)) # print(obj.__next__())
    
    # l1 = [11,22,33,44,55,66]
    # obj = iter(l1)
    # print(next(obj))
    # print(next(obj))
    # print(next(obj))
    # print(next(obj))
    # print(next(obj))
    # print(next(obj))
    
    
    
  • 可迭代对象如何转化成迭代器

    iter([1,2,3])

  • while循环模拟for循环机制

    l1 = [11,22,33,44,55,66,77,88,99,1111,1133,15652]
    # 将可迭代对象转化成迭代器。
    obj = iter(l1)
    while 1:
        try:
            print(next(obj))
        except StopIteration:
            break
    
  • 小结

    • 字面意思:更新迭代,器:工具:可更新迭代的工具。
    • 专业角度:内部含有'__iter__'方法并且含有'__next__'方法的对象就是迭代器。
    • 优点
      1. 节省内存。
      2. 惰性机制,next一次,取一个值。
    • 缺点
      • 速度慢。
      • 不走回头路。
  • 可迭代对象与迭代器的对比

    • 可迭代对象是一个操作方法比较多,比较直观,存储数据相对少(几百万个对象,8G内存是可以承受的)的一个数据集。
    • 当你侧重于对于数据可以灵活处理,并且内存空间足够,将数据集设置为可迭代对象是明确的选择。
    • 迭代器是一个非常节省内存,可以记录取值位置,可以直接通过循环+next方法取值,但是不直观,操作方法比较单一的数据集。
    • 当你的数据量过大,大到足以撑爆你的内存或者你以节省内存为首选因素时,将数据集设置为迭代器是一个不错的选择。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值