文件操作,函数初始到起步,推倒式,迭代器,生成器
作者:互联网
文件操作
只读
使用open()来打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行操作
打开方式的不同能够执行的操作会有相应的差异
打开文件的方式:
r,w,a r+,w+,a+ rb,wb,ab
r模式 只读操作只能进行读取
f=open('文件名称',mode='操作方式',encoding='编码类型')
f.read() 读取
f.close() 关闭文件
f.readline()读行
f.redlines()逐行读取
open中第一个参数放入的是要打开的文件名字,第二个参数是要对这个文件进行什么样的操作,第三参数使用谁让你买编码方式打开文件汇总的内容.
f可以写成任意变量,被称为文件句柄,文件操作符,或者文件操作对象等,open是python调用的操作系统的功能,windows的默认编码方式为gbk,Linux默认编码为utf-8,所以文件用什么编码保存的,就用什么方法打开,mode为打开方式,常见的有r,w,a,r+,a+,w+,rb,wb,ab等 默认不写是r,流程就是打开文件,产生一个文件句柄,对文件句柄进行相应操作,关闭文件.
rb模式:只读字节
f=open('文件名字',mode='rb) #注意在rb,wb,ab,模式不能写encoding
s=f.read()
print(s)
得到的是字节bytes类型
rb作用:在读取分文本的文件的时候,比如读取图像,MP3视频等,就会需要用到rb,因为这种数据是没有办法直接写出来的
用于自己的传输和储存.
相对路径和绝对路径
相对路径:就是在同一级里找,同一个文件夹下,直接写文件名就可以
绝对路径:在电脑磁盘进行查找文件的路径,相当于不知道在哪然后去别的地方找,一直找到文件名
转义
有时候你输入路径的时候
C:\user\ner #这个\n会成为换行符,防止被转义就需要
#两种方法可以防止转义
1.C:\\user\\ner #双斜杠
2.r'C:\user\ner #前面加r
覆盖写 w
写文件的时候要养成好习惯 写完就刷新 flush()
f=open("文件",mode='w',encoding='utf-8')
f.write("内容")
f.flush()
f.close()
当使用w模式的时候,打开文件就会把文件先清空,然后再写入.注意在覆盖写的时候,在打开文件的时候就会把文件清空,
w操作不可以进行进行读取
wb模式,不可以打开文件的编辑,但是写文件的时候必须将字符串转换成utf-8的bytes数据
f=open("文件",mode='wb') 注意一定要不能写encoding
msg='你好'.encode(utf-8)
f.write(msg)
f.flush() #刷新
f.close()
追加a,ab,a+
都是在文件末尾添加,追加,不论光标位置
a,w模式如果文件不存在,都会创建一个新的文件
f=open('内容',mode='a',encoding='utf-8')
msg=f.write("这糖化了以后")
读写模式 r+
读写顾名思义,一定是先读后写,因为光标默认是在前面,当读完了以后,光标读到最后,再进行写
r+模式
f=open("文件名称",mode='r+',encoding='utf-8')
s=f.read()
f.write("针棒")
f.flush()
f.close()
print(s)
#正常的读取,写在结尾
r+模式的坑
在进行读写操作后,如果读取了内容无论多少,光标显示的是多少,再写入或者操作文件的时候都是在结尾进行操作的.
写读模式 W+
f=open("文件名",mode='w+',encoding='utf-8')
先把内容清空,然后写入,然后再读取,但是读取内容是空的,不常用
f=open("文件名",mode='w+',encoding='utf-8')
f.write("xiaogui")
s=f.read()
f.flush()
f.close()
print(s)
读取不到内容,和覆盖写一样,都会清空再写内容
追加读 a+
f=open("文件名",mode='a+',encoding='utf-8')
f.write('内容')
f.flush()
s=f.read()
f.close()
print(s)
a+模式下,无论是先读还是后读都是读不到数据的
其他操作
seek()是移动光标的位置,移动单位是byte字节,所有如果是utf-8的中文部分要是三的倍数
通常用seek都是移动到开头挥着结尾
移动到开头 seek(0,0)
移动到结尾seek(0,2)
移动到当前位置 seek(0,1)
移动一个字:seek(3) 移动光标是按照字节进行移动的
f = open("小娃娃", mode="r+", encoding="utf-8")
f.seek(0,0)将光标移动到开头
s=f.read() 读取内容,此时光标读取完以后移动到结尾
print(s)
f.seek(0) 再次移动到开头
f.seek(0,2) 移动光标到结尾
s1=f.read() 因为光标移动到结尾 所以什么也没读取到
print(s1)
f.seek(0) 将光标移动到开头
f.write("战鼓啊")写入信息,现在光标在9 因为中文的utf-8编码一个中文三字节,3*3=9
f.flush()
f.close()
f.tell() 查看光标位置
tell 查看光标位置:
f = open("小娃娃", mode="r+", encoding="utf-8")
f.seek(0)移动光标到开头
s=f.read() 读取内容,光标移动到结尾
print(s)
f.seek(0) 开头
f.write("美滋滋") 三个字 9个字节
f.tell() 查看光标位置 9
修改文件
文件修改,只能将文件中的内容读取到内存中,将信息修改完毕后删除源文件,将新文件的名字改成旧文件的名字
- 弊端操作,一次将所有内容就行读取,内存溢出
import os
with open("../path1/小娃娃", mode="r", encoding="utf-8") as f1,\ #读
open("../path1/小娃娃_new", mode="w", encoding="UTF-8") as f2: #写
s=f1.read()
new_s=s.replace("冰糖葫芦","大白梨")
f2.write(new_s)
os.remove('文件路径') #删除原文件
os.remove("新文件笔记","旧文件名") #重命名新文件
- 解决方案:一行一行读取和操作
import os
with open("../path1/小娃娃", mode="r", encoding="utf-8") as f1,\ #旧 读
open("../path1/小娃娃_new", mode="w", encoding="UTF-8") as f2: #新 改
for line in f1:
new_line=line.replace("大白梨","冰糖葫芦")
f2.write(new_line)
os.remove("小娃娃") #删除源文件
os.remove("新文件","源文件") #重命名新文件
- 读行 f.readline() 读一行 自动换行
- print(f.readline() .strip()) 读多行 去除换行符
- print(f.readslines()) 一行一行的读取,存放在列表中
- 利用for 循环进行一行一行的获取
函数初始
函数
用函数来实现len
s=[1,2,3,4,5]
count=0
for i in s:
count+=1
print(count)
1、函数的定义:将可重复使用的,实现某种功能的代码段组织在一起
2、函数的语法:
def 函数名(参数):
函数体
return
2.1、函数名是一个变量,因此命名规则需遵守变量命名规则
3、函数的调用
函数名()
4、函数的返回值
return 可空、None、单个、多个的话 以tuple返回给调用者
5、函数的参数:
函数定义时声明的变量的叫形参
1、位置参数
2、默认参数
函数调用时传给函数的叫实参
1、位置参数
定义多少个,调用时也必须传多少个
2、关键字参数
3、混合参数
函数的调用
使用函数名加括号就可以调用函数了当写到函数名加括号,这个函数体就会被执行
def len():
s=[1,2,3,4,5]
count=0
for i in s:
count+=1
print(count)
len() #函数的调用
函数的返回值
def func():
print("1")
func()
func()
func() #多次调用
这样就可以多次调用函数
函数的返回值return
def func():
print(1)
return
func()
return 吧这个结果返回给了调用者 因为return后面没有跟东西 所以默认返回None,并且return以后后续代码不再执行,函数的返回值有多个结果的时候就是返回一个元祖,调用者也可以通过解构获得多个变量,返回给函数的调用者,没有return也是默认返回None
总结return
- 遇到return,此函数结束,return代码不会执行
- return默认是返回None,后面多个返回值是一个元组形式
位置参数需在关键字参数之前
函数的参数
参数是函数括号里的内容,函数在调用的时候回指定一个具体的变量的值,就是参数 def 函数名(参数): 函数体 def func(chat): #形参 print('打开+chat') func(chat) #实参 在调用的时候给chat一个值再执行函数体
2.形参与实参
- 形参,写在函数声明的位置交形参,形式上的完整,表示这个函数需要xxx
- 实参:写在函数的调用的时候给函数传递的值,加实参,实际执行的时候给函数传递的信息,表示给函数xxx
- 传参:从调用函数的时候讲值传递到定义函数的过程叫做传参
3.参数的分类
def func(a,b,c=1): #形参 a,b是关键字参数,c是默认参数 排序就是位置>关键字>默认 prin(a) print(b) print(c) #形参就是变量名 实参就是指 传参就是把值赋值给形参 func(a=2,b=3) #实参
def func(a,b): print(a+b) s=func(1,2) print(s)
- 总结参数:位置参数,关键字参数,混合参数 位置参数必须在关键字参数前面
- 位置参数,按照位置来赋值
- 关键字参数,通过关键字来查找参数
- 默认值参数:有默认值参数通常用默认的值,下面的实参如果给默认值参数赋值,那就会改变成实参赋予的值
用while循环实现for的本质;
s=[1,2,3,4,5]
n=s.__iter__() #迭代器
while True:
try:
print(n.__next__())
except StopIteration:
break
动态参数,名称空间,函数嵌套
函数的动态参数
- *args是万能的位置函数,接收任意多个 args可以变,程序猿统一用args 定义函数时"*"叫聚合,在参数位置用*表示接受任意参数,默认值参数放在动态位置参数后面,这样不会覆盖默认参数的值
- 顺序就是
- 位置顺序 : 位置参数>动态位置参数>
- def song(*args) 这个里面的*\叫做聚合,聚合获得的结果是个元组
- print(a,b,*args)这个里面的叫做打打散,打散可以获得各个元素.
- 动态接收参数的时候注意:动态参数必须在位置参数后面
- 形参的顺序:位置参数>动态参数>默认参数
3.**kwargs 获得的是一个dict字典,接受的关键字参数 *kwargs这个星是可以取这个字典的键 **kwargs万能传参(动态关键字参数)
参数的优先级:位置参数>动态位置参数args>默认参数>kwargs动态关键字参数
- 万能传参:动态位置参数,动态关键字参数
- def song(*args,**kwargs):
- 位置参数>动态位置参数
函数的注释
def func(a,b):
'''
逻辑判断...
:param a:str
:param b:int
return:bool
'''
print(a,b)
def func(user,password):
'''
密码加密
:param user:用户名 str
:param password:密码 str
:return:加密的密码 MDS
'''
print(user,password)
print(func.__doc__)
print(func2.__doc__)
print(func.__name__)
名称空间
print(b)
a=10
def func():
b=20
print(b)
内置空间:print input len 这是python自带的内置空间
全局空间:当前py文件需要开辟的孔家存放在全局空间
局部空间:函数中开辟的空间都是局部空间
加载顺序:
内置空间>全局空间>局部空间
取值顺序:
局部空间>全局空间>内置空间(还找不到就会犯错)
作用域:
全局作用域:内置空间+全局空间
局部作用域:局部空间
函数的嵌套
def song():
print(1)
def fan():
print(2)
return fan()
song()
1,2
____________________
def song():
a=1
def jia():
b=2
print(b)
print(a)
def fan():
pring(b)
return fan()
return jia
song()
2 1 2
____________
def func():
a=1
foo()
pring(a)
def foo():
b=2
print(b)
func()
def a():
a=1
c=()
print(c)
def b():
b=2
print(b)
def c():
c=3
print(a)
def run():
a()
run()
____________________
def func():
a=1
def b():
print(a)
def foo():
b=1
def z():
print(func)
print(b)
ret=z()
func()
return ret
def run():
foo()
print(run())
func 的内存地址 1 还有None
________________________
def func(a):
foo(a)
def foo(e):
b(e)
def b(c):
print(c)
func(15)
15
______________________
a=10
def func():
a=10+1
print(a)
func()
11 别被迷惑
________________
def f1():
a=10
print(a)
def f2():
a=15
print(a)
def f3():
global a
a += 1
print(a)
print(a)
f3()
print(a)
f2()
print(a)
f1()
10 15 11 15 10 10
__________________
a=10
def f1():
a=10
def f2():
a=15
def f3():
global a
a += 1
print(a)
print(a)
f3()
print(a)
f2()
print(a)
f1()
10 10 15 11
—————————————————————
a=100
def func():
global a
a=28
print(a)
func()
print(a)
100 28
____________
a=10
def func1():
a=20
def func2():
nonlocal a
a=30
print(a)
func2()
print(a)
func1()
30 30
___________________
a=1
def fun_1():
a=2
def fun_2():
nonlocal a
a=3
def fun_3():
a=4
print(a)
print(a)
fun_3
print(a)
print(a)
fun_2()
print(a)
print(a)
fun_1()
print(a)
1 2 3 3 3 1
#注意看这个没有被调用的函数
_______________________
global nonlocal
global:修改全局空间的变量对应的值
nonlocal:在外层的函数中修改局部空间变量值,完全不涉及全局空间,只修改上一级离他最近的一层,最近的上一层没有继续往上走,知道找到最外层函数
三元运算符
三元运算符:变量条件成立的结果 条件的判断 条件不成立的结果
return a if a>b else b
a = 10
b = 20
c = a if a> b else b
变量名 = 条件成立的结果 条件 条件不成立的结果
enumerate 枚举
自动排序
enumerate:枚举,对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值。
enumerate(可迭代对象,1) 1决定从几开始计数
li = ['alex','银角','女神','egon','太白']
for i in enumerate(li):
print(i)
(1, 'alex')
(2, '引脚')
(3, '女神')
(4, '太白')
for index,name in enumerate(li,1):
print(index,name)
1 alex
2 引脚
3 女神
4 太白
for index, name in enumerate(li, 100): # 起始位置默认是0,可更改
print(index, name)
100 alex
101 引脚
102 女神
103 太白
函数名的第一类使用对象,f格式化.递归,迭代器
函数名第一类对象及使用
第一类对象的特殊性:
可以当做值赋值给变量
def func():
print("呵呵")
print(func)
a=func
a() #函数调用 func()
a=func 那么 a+()就可以调用这个函数,吧这个函数赋值给一个变量,
当做元素存放在容器中
def func():
print(func)
func()
lst=[func,func,func]
print(lst)
这个列表的每一个元素都是函数func里面的内存地址
函数名可以当作函数的参数
def func():
print(1)
def func1(fn):
print(2)
fn() #执行传递过来的fn
print("666")
func1(func) #吧函数func当成参数传递给func1的参数fn
可以当作函数的返回值
def func():
print(1)
def fun():
print("看我")
return fun
fun=func()
fun()
1, 看我
f格式化
f-strings 是python3.6开始加入的格式化输出的新写法,这个格式化输出比之前的%s或者format高而且更加简化
结果F/f+str的形式,在字符换中想要替换的位置用{}占位,与format类似,但是这个可以直接识别
name=1
age=2
s=f'姓名:{name},性别:{age}'
print(s)
可以加任意表达式
print(f'{2*3}') #6 直接运算结果
name='song'
print(f'全部大写:{name.upper()}') SONG
字典也可以
teacher={'song':'jiafan'}
print(d"the teacher is {teacher['name']}) #大括号里查询字典键就可以导员元素
列表
lst=['song','jiafan']
s=f'姓名:{lst[0]},年龄:{lst[1]}
print(s)
也可以插入表达式
def func(a,b):
return a+b
a=1
b=2
print(f'和+{func(a+b)}')
多行F
name='1'
age=2
sex=1
print(f'姓名{name}\
性别{sex}\
年龄{age}')
其他细节
print(f'{{{g}}}') 两个大括号 打印出啦就是一个大括号 四个就是俩 大括号里面不能出现标点符号 !,:{};
迭代器
可迭代对象定义:有很多私有方法,支持__iter__()方法的就是可迭代对象
迭代器:支持__iter__()方法和__next__()方法的就是迭代器
- 查看对象内部的方法 一种是看源码 一种是通过dir()去判断里面到底有哪些方法
s=123
print(dir(s))
dir会返回一个列表,这个列表含有该对象的整型的所有方法名我们就可以判断是不是可迭代对象了
print('__iter__()'in dir(s)) False 不支持
可迭代对象的优点:可以直观的查看里面的数据,
缺点:占内存,可迭代对象不能迭代取值,出去索引,key以外
for 循环也是在底层做了一个小小的转化才可以迭代取值,将可迭代对象转化成一个迭代器
迭代器
迭代器的定义:**在python中,内部含有__Iter__方法并且含有__next__方法的对象就是迭代器。**
可以通过判断next方法和iter方法来判断哪些是迭代器,哪些是可迭代对象 文件句柄就是一个迭代器剩下的list tuple dict str set 都是可迭代对象
可迭代对象如何转化成迭代器
lst=[1,2,3,4,5] s=lst.__iter__() s=iter(lst) print(s)
迭代器的取值:可迭代对象是不可以一直迭代取值的(出去索引,切片以及key)但是转化成迭代器就可以了他是利用__next__()取值的
lst=[1,2,3,4] s=lst.__iter__() print(s) #内存地址 s1=s.__next__() print(s1) #迭代器取得是值 s1=s.__next__() print(s1) 迭代器是通过next取值的一个next取对应的一个值,如果迭代器里面的值取完了还有next那就StopIteration报错
while模拟for循环内部机制
for循环对象一定是可迭代对象,但是不意味着可迭代对象就可以取值,因为for循环内部机制是:将可迭代对象转换成迭代器,然后用next进行取值,最后利用异常处理处理StopIteration抛出的异常
s=[1,2,3,4,5] s1=s.__iter__() #将可迭代对象转化成迭代器 while True: 利用while循环,next进行取值 try: 利用异常处理终止循环 print(s1.__next__()) except StopIteration: break
迭代器优点:省内存,迭代器在内存只能怪相当于只占一个数据的空间,因为每次取值上一条数据会在内存释放,加载当前的此条数据
惰性机制:next一次,取一个值绝不过多取值
迭代器的缺点:
不能质管的查看里面的数据
取值是不走回头路,只能一直向下取值
可迭代对象和迭代器的对比
可迭代对象操作灵活,私有方法比较多,比如什么增删改查,比较直观,但是占用内存,而且不能直接通过循环迭代取值的这么一个数据集
应用:如果你侧重于对于数据可以灵活处理,而且内存空间足够,将数据集设置为可迭代对象是明确的选择
迭代器:是一个非常节省内存的,可以记录取值位置,可以直接通过for循环加next方法取值,但是不直观,操作方法比较单一的数据集
应用:当你的内存空间比较紧凑的时候,数据量过大的时候,将数据集设置为迭代器是一个不错的选择,
递归:满足两个条件
- 自身调用自身
- 有明确的终止条件
生成器,推导式,内置函数一
1.生成器
python里面三种方式来创建生成器
- 通过生成器函数
- 通过生成器推导式
- python内置函数或者模块提供,python提供的生成器函数
- 把return换成yield就是生成器
def func():
print(111)
yield "222"
g=func() #这个时候函数不会执行,而是获取到生成器
print(g.__next__()) #这个时候函数才会执行
#并且yield会将func生产出来的数据222给了g.__next__()
结果
111
222
return和yield都是返回
yield会记录执行位置
return可以写多个,但是只会执行一次,可以终止函数,并给函数的调用者返回值知识
yield可以写多个会记录执行位置,还可以返回多次,不会终止函数,next会把这个yield对应的内容
def func(): yield "hehe" yield "hehe" yield "hehe" g=func() ret=g.__next__() print(ret) ret1=g.__next__() print(ret1) ret2=g.__next__() print(ret2) #必须一一对应 要不会报错 一个yield对应一个next
5.yield可以在函数内部将for while 循环进行临时暂停
6.next()==__next__() iter()==__iter__() python2和python3中都有next() python2只有next()方法 推荐next()
send()方法(了解)
send和next的区别
相同点:send和next()都可以让生成器对应的yield向下执行一次,都可以获取到yield生成的值
不同: 第一次获取yield值只能是用next不能用send(可以用send(None))send可以给上一个yield值传递值
yield from
python3提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回
yield将可迭代对象元素逐个返回
def func():
lst=[1,2,3,4,5]
yield lst
g=func()
print(g) #返回func内存地址
print(next(g)) #只是返回一个列表
def func():
lst=[1,2,5,3,4]
yield from lst
g=func()
print(g) #内存地址
print(next(g))# 返回的是一个列表的元素 多了也会报错
def func():
lst=[1,2,3,4,5]
lst1=[9,8,7,6,5]
yield from lst1 #先执行这个lst1列表的元素
yield from lst #挨个返回后再执行lst的元素
g=func()
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
2.推导式
- 列表推导式
向列表中添加1~10
print([i for i in range(10)])
简洁 推导这个从0-9十个数的打印
lst=[]
for i in range(10):
lst.append(i)
print(lst)
列表推导式分为两种模式:
- 循环模式:[变量(加工的变量)for 变量 in iterable ]
- 筛选模式:[变量(加工的变量)for 变量 in iterable if条件]
3.循环模式
lst=[i*i for i in range(10) ] 十以内数字的所有整数平方 这个i*i就是加工的变量 lst=[f'python{i}期'for i in range(10)] print(lst) 从python0期到python9期 f'python{i}期'就是加工的变量
3.筛选模式
筛选模式就是在上面基础上添加一个条件判断,然后将满足条件的添加到列表中
把lst=[1,2,3,4,5,6,7,8]这个列表中的大于三的留下来 lst=[1,2,3,4,5,6,7,8] print([i for i in lst if i>3]) 把列表元素长度小于三的筛选掉 把剩下的全部大写 l = ['wusir', 'laonanhai', 'aa', 'b', 'taibai'] print([i.upper() for i in l if len(i)>3])
找到嵌套列表中名字含有两个‘e’的所有名字(有难度) names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] print([name for lst in names for name in lst if name.count('e') >= 2]) # 注意遍历顺序,这是实现的关键
4.生成器表达式
生成器表达式和列表推导式的语法一模一样,只是把[]换成()就行了
比如八十以内的所有丨的平方放到一个生成器表达式中 s=(i**2 for i in range(10)) print(s) 得到是内存地址 #生成器表达式也可以进行筛选 获取1-100能被三整除的数 s=(i for i in range(100) if i%3==0) for i in s: print(i)
生成器表达式和列表推导式的区别:
- 列表推导式比较消耗内存,所有数据一次性加载到内存.而生成器表达式遵循迭代器协议,逐个产生元素
- 得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器.
- 列表推导式一目了然生成器表达式知识一个内存地址.
生成器的惰性机制:生成器只有在访问的时候才取值,找他要才给你值,不要就不会执行
字典推导式:
lst=[1,2,3] lst1=["nihao","hello","hey"] dic={lst[i]:lst[i] for i in range(len(lst))} print(dic)
集合推导式;生成一个集合,集合特点无序不重复 所以结婚推导式天然去重
print({i for i in [-13,-13,2,2,3] })
3.内置函数一
s = """for i in range(10): print(i)"""s1 = """def func(): print(123)func()"""print(eval(s))print(exec(s1)) # 牛逼 不能用print(hash("asdfas"))print(help(list))help(dict)def func(): passprint(callable(func)) # 查看是否可调用print(float(2)) # 浮点数print(complex(56)) # 复数print(oct(15)) # 八进制print(hex(15)) # 十六进制print(divmod(5,2)) # (2, 1) 2商 1余print(round(5.3234,2)) # 四舍五入 -- 默认是整数,可以指定保留小数位print(pow(2,3)) # 幂print(pow(2,3,4)) # 幂,余s = "alex"print(bytes(s,encoding="utf-8"))print(ord("你")) # 当前编码print(chr(20320))s = "C:\u3000"print(repr(s))print("\u3000你好")lst = [1,2,3,False,4,5,6,7]print(all(lst)) # 判断元素是否都为真 相似andprint(any(lst)) # 判断元素是否有真 相似orname = 1def func(): a = 123 # print(locals()) # print(globals())func()print(globals()) # 全局空间中的变量print(locals()) # 查看当前空间的变量
这些是不常用的内置函数,了解即可
标签:函数,迭代,推倒,生成器,next,func,print,def 来源: https://www.cnblogs.com/sjf981012-/p/11223190.html