文件操作到函数

他来了,他来了,他憋着尿来了
各位好,我来了,今天不困,很奇怪,破天荒,感觉有大事要发生了,果然,晚上就有朋友说我博客写得好,给我打赏了十块钱。

好了,开心的进入打气环节,今天的憨憨们有没有给自己打气呀?

今日洗脑金句: 加油,对抗赖床不容易,python给你爆发力!

文件的高级应用

一、可读and可写

  • r+t: 可读、可写 (没用)
  • w+t: 可写、可读 (没用 too)
  • a+t: 可追加、可读 (没用 too too)

img

不是,没用的东西为什么要造出来呢。

原来是因为有弊端

来我们看看

我们知道读写文件的时候的写法open方法里面的第二个参数是写r 或者 w 或者 a,各是什么用的如果你们忘记了,先毒打自己一顿,然后去看我上一篇博客。

但是,其实第二个参数是要写rt 或者wt 或者at的,因为这样就是以文本的形式读取文件,把t改成b的话就是以二进制的形式读取文件,通常用来读取图片音频之类的。

所以,不写的话就是默认t,以文本的方式读取文件。

img

来讲讲为什么这些没用吧

因为有延迟。

如果你已既可读又可写的形式打开了一个文件,然后往里头写了点东西,然后又读,有可能会出现你没有读取到你刚写进去的东西,为什么呢,因为时间延迟啊,这个时候你并不知道发生了什么,于是死倔强的你又憨批的重新写了一次,这时候会怎么样,报错!

所以这就是为什么他们没卵用的原因,不仅没卵用,更是不提倡大家去用啊。

二、文件内指针移动

好的,这个就是有用的东西了

img

这个东西是干嘛用的呢

如果我们想要在文件内容中的某一行增加内容,实用基础的r/w/a模式实现是非常困难的(但并不是不行,老子就行),因此我们需要对文件内的指针进行移动。哦这个时候就有同学会问了

”为什么我不可以去文件里面直接增加内容呢?“

img

你为什么不直接把电脑机箱打开用机械手臂去刮磁道增加呢?

我们在讲的是用代码实现,代码!代码!

首先,先搞清楚什么是指针,指针就是光标,指针在哪里,你的输入内容就在哪里。

with open('36r.txt', 'r+t', encoding='utf-8') as fr:
    fr.readline()
    fr.write('力哥真帅啊')  # 写在文件的最后一行

硬盘上从来没有修改一说,硬盘上只有覆盖,即新内容覆盖新内容。

1.seek(offset,whence): offset代表文件指针的偏移量,偏移量的单位是字节个数

# seek()
with open('36r.txt', 'rb') as fr:
    print(f"fr.seek(4, 0): {fr.seek(4, 0)}")  # 0相当于文件头开始;1相当于当前文件所在位置;2相当于文件末尾
    # fr.seek(0,2)  # 切换到文件末尾
fr.seek(4, 0): 3

2.tell(): 每次统计都是从文件开头到当前指针所在位置

# tell()
with open('36r.txt', 'rb') as fr:
    fr.seek(4, 0)
    print(f"fr.tell(): {fr.tell()}")
fr.tell(): 4

3.read(n): 只有在模式下的read(n),n代表的是字符个数,除此之外,其他但凡涉及文件指针的都是字节个数

# read()
with open('36r.txt', 'rt', encoding='utf-8') as fr:
    print(f"fr.read(3): {fr.read(3)}")
fr.read(3): sdf

4.truncate(n): truncate(n)是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate()要在r+或a或a+等模式下测试效果。它的参照物永远是文件头。并且truncate()不加参数,相当于清空文件。

# truncate()
with open('36r.txt', 'ab') as fr:
    fr.truncate(2) # 截断2个字节后的所有字符,如果3个字节一个字符,只能截断2/3个字符,还会遗留1/3个字符,会造成乱码

以上的方法都是极其重要的方法,所以为了各位能够不被影响的学会这些方法,我就用了比较朴素易懂的话语来表述了一下,绝对不是因为CV大法真香

img

记得不要用既可读又可写的模式打开文件哦!

修改文件的两种方式

文件的数据是存放在硬盘上的,他只存在覆盖的情况,不存在修改的说法,我们看到的修改都是假象。

是不是就像告诉你你从小吃的饭都是牛粪变的一样让你无法接受?

来我解释给你听,这里不得不再一次祭出我璀璨星辰一般的画技了。

img

首先我们看,这是一块内存,上面有系统文件,你要修改的文件,以及若干大数量毛片。这个时候你要往你要修改的文件中加一些内容,那么他的内存占用是不是会变大?大了怎么办,叫系统文件往前挤挤?让毛片往后挪挪?很明显都不行,其实在你修改的时候,都是有缓存文件的,你改完之后直接就删除了原来的文件,然后把缓存文件改名为原来文件的名字,让你看上去就好像是修改了一样,实则是覆盖!

好,接下来介绍一下两种修改的方式

一、方式一(憨批方式)

将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(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')
print('done...')

done...

直接把文件全读出来然后改,这还不憨批?

对不起,对不起,今天是8/19号,我来改博客了,截至目前为止,我一直都是用这种方式改文件的,不憨批,一点儿也不憨批。

二、方式二

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

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')
print('done...')
done...

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

函数的定义

一、函数体系

这玩意儿看过一下就好了,到时候会一个一个讲的

  • 什么是函数?
  • 为什么要用函数?
  • 函数的分类:内置函数与自定义函数
  • 如何自定义函数
    • 语法
    • 定义有参数函数,及有参函数的应用场景
    • 定义无参数函数,及无参函数的应用场景
    • 定义空函数,及空函数的应用场景
  • 调用函数
    • 如何调用函数
    • 函数的返回值
    • 函数参数的应用:形参和实参,位置形参,位置实参,关键字实参,默认形参,*args,**kwargs
  • 高阶函数(函数对象)
  • 函数嵌套
  • 作用域与名称空间
  • 装饰器
  • 迭代器与生成器及协程函数
  • 三元运算,列表解析、生成器表达式
  • 函数的递归调用
  • 内置函数
  • 面向过程编程与函数式编程

二、什么是函数

假设你是一个恐怖分子,要去爆破一个军事要塞。正常人都会带zhayao过去,而不会去军事要塞现场制作zhayao,弟弟行为。这个zhayao,就是你要是用的工具,就是函数,当然函数是可以重复使用的,这点就不要说zhayao是一次性的跟我刚了,再刚你也是一次性的了。

img

三、为什么要用函数

就是这个带zhayao还是现场制作的问题。

四、如何使用函数

用def +函数名 +‘:’就好了

定义函数的三种形式

一、无参函数

定义函数时参数是函数体接收外部传值的一种媒介,其实就是一个变量名

在函数阶段括号内没有参数,称为无参函数。需要注意的是:定义时无参,意味着调用时也无需传入参数。

如果函数体代码逻辑不需要依赖外部传入的值,必须得定义成无参函数。

def func():
    print('hello nick')
    
func()  # hello nick

二、有参函数

如果函数体代码逻辑需要依赖外部传入的值,必须得定义成有参函数。

def sum_self(x, y):
    """求和"""
    res = x+y
    print(res)

sum_self(1,2)  # 3

三、空函数

def func():
    pass

函数的返回值

一、什么是返回值

就是你炸弹的结果啦,

用return返回

炸弹的结果是爆炸

当然可以用return返回各种类型的数据

二、为什么要有返回值

没返回值的函数,就相当于不会爆炸的哑弹。毫无意义

你说你辛辛苦苦写的函数,最后什么回馈都没有,你写她来做什么,有什么意义呢?

函数的调用

一、什么是函数的调用

就是你把函数名写下来,他就被调用了,直到碰到return 或者执行完函数里面的全部代码之后才会停下来。如果没有写return,就会返回一个none

二、调用函数的三种形式

def max_self(x,y):
    if x>y:
        return x
    else:
        return y
    
# 1.
max_self(1,2)
# 2.
res = max_self(1,2)*12
# 3.
max_self(max_self(20000,30000),40000)

函数的参数

1.1形参

def func(x, y):
    print(x)
    print(y)

1.2 实参

func(1, 2)

二、位置参数

**位置形参

def func(x, y):
    print(x)
    print(y)

特点:按照位置定义的形参,都必须被传值,多一个不行,少一个也不行。

2.2 位置实参

func(1, 2)

特点:按照位置为对应的形参依次传值。

三、关键字实参(憨批东西,这辈子我都不用,除非有特殊情况)

在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参。

func(y=2, x=1)

特点:可以打破位置的限制,但仍能为指定的形参赋值。

注意:

  1. 可以混用位置实参和关键字实参,但是位置实参必须在关键字实参的左边。
  2. 可以混用位置实参和关键字实参,但不能对一个形参重复赋值。
func(x, y=2)
func(y=2, x)  # SyntaxError: positional argument follows keyword argument
func(x, x=1)  # NameError: name 'x' is not defined

四、默认形参

在定义阶段,就已经被赋值。

def func(x, y=10):
    print(x)
    print(y)
    
func(2)

特点:在定义阶段就已经被赋值,意味着在调用时可以不用为其赋值。

注意:

  1. 位置形参必须放在默认形参的左边。
  2. 默认形参的值只在定义阶段赋值一次,也就是说默认参数的值在函数定义阶段就已经固定了。
m = 10


def foo(x=m):
    print(x)


m = 111
foo()  # 10
  1. 默认参数的值通常应该是不可变类型。
# 演示形参是可变类型
def register(name, hobby, hobby_list=[]):
    hobby_list.append(hobby)
    print(f"{name} prefer {hobby}'")
    print(f"{name} prefer {hobby_list}")


register('nick', 'read')
register('tank', 'zuipao')
register('jason', 'piao')
nick prefer read'
nick prefer ['read']
tank prefer zuipao'
tank prefer ['read', 'zuipao']
jason prefer piao'
jason prefer ['read', 'zuipao', 'piao']
# 修改形参是可变类型代码
def register(name, hobby, hobby_list=None):
    if hobby_list is None:
        hobby_list = []
    hobby_list.append(hobby)
    print(f"{name} prefer {hobby}'")
    print(f"{name} prefer {hobby_list}")


register('nick', 'read')
register('tank', 'zuipao')
register('jason', 'piao')
nick prefer read'
nick prefer ['read']
tank prefer zuipao'
tank prefer ['zuipao']
jason prefer piao'
jason prefer ['piao']

总而言之,用什么还是看个人习惯

func(这里放几个参数不就完事儿了?搞得花里胡哨,人生苦短啊!)

今日朝贡就到这里了,没事就退下吧,朕乏了。去尿尿了。

posted @ 2019-08-08 22:17  chanyuli  阅读(277)  评论(0编辑  收藏  举报