文件操作
1,文件路径
2,编码方式:utf-8.
3,动作mode,读,读写,写读.
f1 = open('D:\a.txt', encoding='utf-8', mode='r')
content = f1.read()
print(content)
f1.close()
#f1,文件句柄,文件对象,file,f_handle,file_handle,f_obj open打开的指令,windows的指令,
#windows 默认编码方式gbk,linux默认编码方式utf-8,mac utf-8。
1,打开文件,产生文件句柄。
2,操作文件句柄。
3,关闭文件。
#SyntaxError: (unicode error) 'unicodeescape' codeccan't decode bytes in position 2-3: truncated \UXXXXXXXX escape
f1 = open(r'D:\a.txt', encoding='utf-8', mode='r') #有绝对路径文件前面写上 r 代表转义
f1 = open('D:\\a.txt', encoding='utf-8',mode='r') #绝对路径不写 r 必须在路径D:\a.txt加上\来转义
EncodeDecodeErorr: 编码错误。
r 模式—读
f1 = open('D:\a.txt', encoding='utf-8', mode='r') #默认为都模式 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) : r 模式 按照字符读取
f1 = open('log1', encoding='utf-8')
content = f1.read(5) # r 模式 按照字符读取。
print(content) #更加快乐的
f1.close()
rb 模式 –按照字节读取
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()
#更加快乐的附件
#fdsaklf;jdsaf
#fdsakjfdsaf 多岁的发生
#fd66666666
readlines()—将每一行作为列表的一个元素并返回这个列表
f1 = open('log1', encoding='utf-8')
print(f1.readlines()) #['更加快乐的附件\n', 'fdsaklf;jdsaf\n', 'fdsakjfdsaf 多岁的发生\n', 'fd66666666\n', '6666']
f1.close()
for 循环
f1 = open('log1', encoding='utf-8')
for i in f1:
print(i)
f1.close()
#更加快乐的附件
#fdsaklf;jdsaf
#fdsakjfdsaf 多岁的发生
#fd66666666
#6666
decode:解码 成unincod
encode:指定解析成utf-8、gbk编码显示
f2 = open('log1',mode='rb')
print(f2.read())
f2.close()
#编码的补充:\
s1 = b'\xd6\xd0\xb9\xfa'
s2 = s1.decode('gbk')
s3 = s2.encode('utf-8')
print(s3) # b'\xe4\xb8\xad\xe5\x9b\xbd'
s1 = b'\xd6\xd0\xb9\xfa'.decode('gbk').encode('utf-8')
print(s1)
r+ 读写模式 先全部读取出来,写入的数据不会显示
f1 = open('log1', encoding='utf-8', mode='r+')
print(f1.read())
f1.write('\n666')
f1.close()
seek(0)#调整光标到文件首个
seek(0,2)#调整光标到文件最末尾
* seek(参数)、光标 按照字节去运转(调整)*
f1 = open('log1', encoding='utf-8', mode='r+')
f1.seek(0,2)
f1.write('\n6666')
f1.seek(0)#调整光标
print(f1.read())
# #光标 按照字节去运转 seek
f1.close()
w 模式—写 (一直覆盖)
w write() 写 一直覆盖
wb 模式 一直覆盖 写入进去的是字节,要转化成utf-8 或gbk
f1 = open('log2', encoding='utf-8', mode='w')
f1.write('sb是披着高富帅外衣的纯屌丝.....')
f1.close()
#sb是披着高富帅外衣的纯屌丝.....
f1 = open('log2', mode='wb')
f1.write('\nalex是披着高富帅外衣的纯屌丝llLLlll.....'.encode('utf-8'))
f1.close()
#
#alex是披着高富帅外衣的纯屌丝llLLlll.....
w+ 写读模式 看到的永远是你写进去的东西,移动光标也不可以
f1 = open('log2', encoding='utf-8', mode='w+')
f1.seek(0,2)
f1.write('666')
f1.seek(0)
print(f1.read()) ###移动光标也不可以 看到的永远是你写进去的东西
f1.close()
#666
a ab a+ 模式
a 模式—追加
f1 = open('log2', encoding='utf-8', mode='a')
f1.write('\n老男孩')
f1.close()
#666
#老男孩
ab 模式 : 按字节追加 需要把编码解析成 utf-8 或 gbk
f1 = open('log2', mode='ab')
f1.write('\naaa'.encode('utf-8'))
f1.close()
#666
#aaa
a+ 模式 :追加进去之后调整光标 可以全部读取
f1 = open('log2', encoding='utf-8', mode='a+')
f1.write('\nfdsafdsafdsagfdg')
f1.seek(0)
print(f1.read())
f1.close()
#666
#aaa
#fdsafdsafdsagfdg
其他操作方法:
read:全部读取、read(n):按字符读取到第n个字符、readline():按行读取、readlines():将每一行作为列表的一个元素并返回这个列表、write():写、close():关闭文件
readable writable
seek(参数)、光标 按照字节去运转(调整)
tell() :告诉指针的位置
f1 = open('log2', encoding='utf-8', mode='w')
f1.write('fdsafdsafdsagfdg')
print(f1.tell())
f1.close()
#16
with 不需要close关闭文件
whit open() as :
with open('log1', encoding='utf-8') as f1,\
open('log2', encoding='utf-8', mode='w')as f2:
print(f1.read()) #读取log1全部内容
f2.write('777') #写入777到log2 (覆盖)
文件的改
#1,打开原文件,产生文件句柄。
#2,创建新文件,产生文件句柄。
#3,读取原文件,进行修改,写入新文件。
#4,将原文件删除。
#5,新文件重命名原文件。
alex是老男孩python发起人,创建人。
alex其实是人妖。
谁说alex是sb?
你们真逗,alex再牛逼,也掩饰不住资深屌丝的气质。
小题:把上文里的alex 替换成SB
第一种方法:
import os
with open('file_test', encoding='utf-8') as f1,\
open('file_test.bak', encoding='utf-8', mode='w') as f2:
old_content = f1.read()
new_content = old_content.replace('alex','SB')
f2.write(new_content)
os.remove('file_test')
os.rename('file_test.bak','file_test')
第二种方法:for循环
import os
with open('file_test', encoding='utf-8') as f1,\
open('file_test.bak', encoding='utf-8', mode='w') as f2:
for line in f1:
new_line = line.replace('SB','alex')
f2.write(new_line)
os.remove('file_test')
os.rename('file_test.bak','file_test')
函数的初识
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print(),len()等。
函数的定义与调用
def 关键字 函数名(设定与变量相同):
函数体
模拟len()
#计算s1的长度
s1 = 'fdsgdfkjlgdfgrewioj'
#函数的定义
def my_len():
count = 0
for i in s1:
count += 1
print(count)
#函数调用
my_len() # 函数名+() 执行函数
定义:
def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。
def 是固定的,不能变,他就是定义函数的关键字。
空格 为了将def关键字和函数名分开,必须空(四声),当然你可以空2格、3格或者你想空多少都行,但正常人还是空1格。
函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能
括号:是必须加的,先别问为啥要有括号,总之加上括号就对了!
注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。
调用:就是 函数名() 要记得加上括号。
return:函数的返回值
#计算s1的长度
s1 = 'fdsgdfkjlgdfgrewioj'
#函数的定义
def my_len():
count = 0
for i in s1:
count += 1
return count
print (my_len) #19 <class 'int'>
#函数调用
my_len() # 函数名+() 执行函数
#19 <class 'int'>
1、遇到return,结束函数
def func1():
print(11)
print(22)
return
print(333)
print(444)
func1()
#11
#22
2、给函数的调用者(执行者)返回值.
无 return 返回None
return 不写 或者 None 返回None
return 返回单个数.
return 返回多个数,将多个数放在元组中返回。
返回多个数
def my_len():
count = 0
for i in s1:
count += 1
return 666,222,count,'老男孩'
print(my_len(),type(my_len()))
#(666, 222, 19, '老男孩') <class 'tuple'>
函数的参数
li = [1, 2, 3, 43, 'fdsa', 'alex']
s1 = 'fdsgdfkjlgdfgrewioj'
def my_len(a): # 函数的定义()放的是形式参数,形参
count = 0
for i in a:
count += 1
return count
ret = my_len(li) # 函数的执行() 实际参数,实参
print(ret) #6
print(len(s1)) #9
我们告诉mylen函数要计算的字符串是谁,这个过程就叫做 传递参数,简称传参,我们调用函数时传递的这个“li变量”和定义函数时的s1就是参数。
实参角度
1、位置参数。 必须一一对应,按顺序
def func1(x,y):
print(x,y)
func1(1, 2)
2、关键字参数。必须一一对应,不分顺序。
def func1(x,y,z):
print(x,y,z)
func1(y=2,x=1,z=5,)
比较大小
第一种方法
def max(a,b):
if a > b:
return a
else:
return b
print(max(100,102))
第二种方法
def max(a,b):return a if a > b else b
print(max(100,102))
3、混合参数.一一对应 且 关键字参数必须在位置参数后面
def func2(argv1,argv2,argv3):
print(argv1)
print(argv2)
print(argv3)
func2(1,2,argv3=4)
从形参角度
1、位置参数。 必须一一对应,按顺序
def func1(x,y):
print(x,y)
func1(1,2)
2、默认参数。 必须在位置参数后面。
def register(name,sex='男'):
with open('register',encoding='utf-8',mode='a') as f1:
f1.write('{} {}\n'.format(name,sex))
while True:
username = input('请输入姓名:/q 或者 Q 退出')
if username.upper() == 'Q':break
if 'a' in username:
sex = input('请输入性别:')
register(username,sex)
else:
register(username)
3、动态参数 *args,(**kwargs )万能参数
def func2(*args,**kwargs):
print(args) # 元组(所有位置参数)
print(kwargs)
func2(1,2,3,4,5,6,7,11,'alex','老男孩',a='ww',b='qq',c='222')
#(1, 2, 3, 4, 5, 6, 7, 11, 'alex', '老男孩')
#{'a': 'ww', 'b': 'qq', 'c': '222'}
位置参数,*args,默认参数
def func3(a,b,*args,sex='男'):
print(a)
print(b)
print(sex)
print(args)
func3(1,2,'老男孩','alex','wusir',sex='女')
#1
#2
#女
#('老男孩', 'alex', 'wusir')
位置参数,*args,默认参数,**kwargs
def func3(a,b,*args,sex='男',**kwargs):
print(a)
print(b)
print(sex)
print(args)
print(kwargs)
func3(1,2,'老男孩','alex','wusir',name='alex',age=46)
#1
#2
#男
#('老男孩', 'alex', 'wusir')
#{'name': 'alex', 'age': 46}
函数的定义:形参里有 * 是聚合
函数的执行:* 打散功能
def func1(*args): #函数的定义 * 聚合。
print(args)
l1 = [1,2,3,4]
l11 = (1,2,3,4)
l2 = ['alex','wusir',4]
func1(l1,l2,l11)
#([1, 2, 3, 4], ['alex', 'wusir', 4], (1, 2, 3, 4))
func1(*l1,*l2,*l11) 函数的执行:* 打散功能
#(1, 2, 3, 4, 'alex', 'wusir', 4, 1, 2, 3, 4)
**kwargs同上
def func1(**kwargs): #函数的定义 ** 聚合。
print(kwargs)
dic1 = {'name1':'alex'}
dic2 = {'name2':'laonanhai'}
func1(dic1,dic2) #({'name1': 'alex'}, {'name2': 'laonanhai'})
func1(**dic1,**dic2) #{'name1': 'alex', 'name2': 'laonanhai'}
函数的进阶
name = 'alex'
age = 12
def func1():
name1 = 'wusir'
age1 = 34
func1()
print(name1) #报错 显示没有name1这个变量
上面为什么会报错呢?现在我们来分析一下python内部的原理是怎么样:
我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。
等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
我们给这个‘存放名字与值的关系’的空间起了一个名字——-命名空间。
代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间。
命名空间和作用域
命名空间一共分为三种:
全局命名空间
局部命名空间
内置命名空间
内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple…它们都是我们熟悉的,拿过来就可以用的方法。
三种命名空间之间的加载与取值顺序:
加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)
取值顺序:
在局部调用:局部命名空间->全局命名空间->内置命名空间
在全局调用:全局命名空间->内置命名空间
综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。
作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
局部作用域:局部名称空间,只能在局部范围内生效
globals:查看全局命名空间的名字
locals:查看局部命名空间的名字
name1 = 'wusir'
def func1():
name2 = 'laonanhai'
print(globals())
print(locals())
func1()
#{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002A16C79A0F0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/python自动化/day03/06 函数的进阶.py', '__cached__': None, 'name1': 'wusir', 'func1': <function func1 at 0x000002A16C8651E0>}
#{'name2': 'laonanhai'}
关键字:global、nonlocal
global:
1、声明一个全局变量
2、更改一个全局
name = 'wusir'
def func1():
global name
name = 'alex'
return
func1()
print(name)
#alex
nonlocal :
1,不能修改全局变量。
2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
def func1():
name1 = 'alex'
print('+',name1)
def inner():
nonlocal name1
name1= 'wusir'
print('*',name1)
def inner1():
pass
inner()
print('%',name1)
func1()
#+ alex
#* wusir
#% wusir
函数名
1、可以相互赋值
def func1():
print(666)
f1 = func1
f1()
#666
2、函数名可以当成函数的参数
def func1():
print(666)
def func2(argv):
argv()
print(777)
func2(func1)
#666
#777
3、可以当成容器类数据类型的参数
def func1():
print(666)
def func2():
print(777)
def func3():
print(888)
l1 = [func1, func2, func3]
for i in l1:
i()
#666
#777
#888
4、函数名可以当成函数的返回值
def func1():
print(666)
def func2(argv):
print(777)
return argv
ret = func2(func1)
ret()
#777
#888
闭包
定义:内层函数对外层函数非全局变量的引用,叫做闭包
闭包的好处:如果python 检测到闭包,他有一个机制,你的局部作用域不会随着函数的结束而结束
1、判断是不是闭包
print(inner.closure) # #(,) 是闭包
def wrapper():
name1 = '老男孩'
def inner():
print(name1)
inner()
print(inner.__closure__) #(<cell at 0x000001FE223C7498: str object at 0x000001FE224435D0>,)
wrapper()
#老男孩
出现 print(inner._closure_) #None
name1 = '老男孩'
def wrapper():
def inner():
print(name1)
inner()
print(inner.__closure__) # None
wrapper()
#None