day03 文件操作 函数 参数 返回值 作用域和名称空间 global和nonlocal

一.文件

(一)文件操作
  open(文件, mode="", encoding="utf-8")
  文件读取: r(read)
  1. readline() 读取一行
  2. for循环 读取每一行内容
    不能写

  向文件中写入内容: w(write), a(append)
  write() 写出内容
  不允许读取

  其他模式: rb, wb, ab b:bytes 不需要encoding
  带b的用来操作非文本文件(图片, 视频, 音频)

  其他模式: r+, w+, a+ +:扩展
  一个文件. 要么读, 要么写
    r+ 在读的基础上扩展. 读写操作
    w+ 写读操作
    a+ 追加写读操作

  其他模式:r+b, w+b, a+b 操作的是字节

(二)文件修改操作(重点和难点):
  1. 读取源文件中的内容
  2. 修改内容
  3. 把新内容写入到副本文件
  4. 删除源文件
  5. 把副本文件重命名成源文件
  import os
    os.remove() 删除文件
    os.rename() 重命名文件


(三)文件操作补充:
  f.seek(0) 光标移动到开头
  f.seek(0, 2) 光标移动到末尾

  第二个参数表示模式:
    0: 文件的开头,默认值
    1: 光标当前位置
    2: 文件的末尾

  f.tell() 告诉你光标当前的位置
  f.truncate() 截断文件

(四)文件读取练习:

二.函数
(一)函数是对功能或者动作的封装.
  def 函数名(形参):
  函数体

  函数名(实参)
(二)参数
  1. 实参: 函数调用
    1. 位置参数
    2. 关键字参数
    3. 混合参数. 位置 -> 关键字
  2. 形参: 函数声明
    1. 位置参数
    2. 默认值参数
  3. 动态传参
    1. *args 接收位置参数的动态传参
    2. **kwargs 接收关键字参数的动态传参
  4.形参列表: 位置 -> *args -> 默认值 -> **kwargs

  5.*和**. 在形参:聚合 在实参:打散

  def func(*args, **kwargs): # 无敌
    pass


(三)返回值(return)
  函数如果执行到return. 结束该函数
  1. return 值. 返回一个结果
  2. 只写return或者不写return. 返回None
  3. return 值1, 值2, 值3..... 返回多个结果

(四)名称空间
  1. 内置
  2. 全局
  3. 局部
(五)作用域
  1. 全局
  2. 局部

  globals() 查看全局作用域
  locals() 查看当前作用域

(六)函数的嵌套
  global:把全局中的变量引入到局部
  nonlocal:在局部...把离他最近的外层函数中的局部变量引入到当前.


(七)函数名就是一个变量名

具体内容:

一.补充知识点:创建一个字典

Fromkeys:

dic={}
dic.fromkeys("jay","方文山")#创建字典
print(dic)#结果为{}

这个程序中fromkeys是创建新字典和原来的dic无关.上述结果是空字典{}

dic={}
d=dic.fromkeys("jay","方文山")#创建字典
print(d)#结果为{{'j': '方文山', 'a': '方文山', 'y': '方文山'}

fromkeys执行的效果就是把前面的字符串进行迭代,分别和后面的参数组合成key:value.创建一个新字典.

神坑1:fromkeys返回新字典,不是原来字典的基础上干活的.

下面是这fromkeys()的正确用法,上面的方式也可以,但是不规范的,不建议用.

dic={}
print(dic.fromkeys("国产化","葫芦娃"))#{'国': '葫芦娃', '产': '葫芦娃', '化': '葫芦娃'}

神坑2:所有的key共享一个value

dic={}
d=dic.fromkeys("国产化",["葫芦娃"])#{'国': '葫芦娃', '产': '葫芦娃', '化': '葫芦娃'}
d[""].append("娜扎")#{'国': ['葫芦娃', '娜扎'], '产': ['葫芦娃', '娜扎'], '化': ['葫芦娃', '娜扎']}
print(d)#{'国': ['葫芦娃', '娜扎'], '产': ['葫芦娃', '娜扎'], '化': ['葫芦娃', '娜扎']}

因为三个key指向的是同一个列表[葫芦娃],如果把[葫芦娃]+[娜扎],整个列表就改变了.

二.文件操作

(一)文件的读:read

1.open(文件,mode=””,encoding=”文件的编码格式”)

#encode(“utf-8”)编码

#encoding”tuf-8”用utf-8编码和解码

#percharm默认的是所有utf-8

2.文件读取:r读取read

3.句柄:f就是这个文件的句柄.用f操作这个文件,防止这个文件很大,直接超过内存,把内存撑爆了.

f就是和文件交互的通道,从文件里面读东西,和把文件加载出来后,再操作.是一样的

f=open("四驱兄弟",mode="r",encoding="utf-8")
content=f.read(2)#读取文件内容的前2个字符
print(content)#四驱
f.close()

#f.read(2)把文件中的内容一次读取出来,2表示读取两个字符.

#如果只读取字符,操作麻烦

4.解决方法:读取readline()#与readlines()

f=open("四驱兄弟",mode="r",encoding="utf-8")
line1=f.readline()
line2=f.readline()
print(line1,line2)
f.close()

readlines()#一次性读取一个列表,也存在读取文件太大的问题.

f=open("四驱兄弟",mode="r",encoding="utf-8")
lst=f.readlines()
print(lst)#['四驱兄弟....\n', '1.该作品讲述RF日本胜利队的\n', '2.时代已经结束,他们在向第\n', '3.二届迷你四驱车世界杯大赛\n', '4.的主办地美国迈进,一文字\n', '5.政宗所开发的空气动力底盘\n', '6.成为了新的开端。']

5.光标:记录当前位置

当光标挪到末尾,就无法读取东西.

如果重新调取,可以把光标上移,

f.seek(0)#把光标移到首位

6.print(“”)#末尾也是默认有换行

默认:end=”\n”如果去掉\n,哈哈哈和呵呵呵就变成一行了.

print("haha",end="")#end="\n 是print默认的程序
print("hehehe")#hahahehehe

7.这行内容里面有默认的换行”\n”

锄禾
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦

去掉解决方法是strip()#readlines()不能倍strip()

f=open("四驱兄弟",mode="r",encoding="utf-8")
d=f.readline()
print(d.strip())

8.文件句柄可以迭代

f=open("四驱兄弟",mode="r",encoding="utf-8")
for line in f:
    print(line.strip())

(二)文件的写write

1.向文件中写入内容:w(write).append()

# f = open("锄禾",mode="r",encoding="utf-8")#No such file or directory: '锄禾'
f = open("锄禾",mode="w",encoding="utf-8")
# print(f.read())#报错not readable
f.write('''锄禾
锄禾日当午
汗滴禾下土
谁知盘中餐
粒粒皆辛苦''')

#第一个报错:这个报错,因为没有这个文件

#如果改成w,就会自动创建文件,如果文件存在把文件内容清空.所以一般情况不用.

#最后一个报错,因为在w的模式下,不能read.只能用f.write写入.

#应用场景:用户上传头像,清除之前文件.

2.两个好习惯

#f.flush#刷新管道

#f.close:文件关闭

3.rb,wb,ab,b:bytes,不需要encoding.一般用来操作非文本文件(图片\视频\音频)

因为图片\视频\音频不是utf-8

例如:把c中文件复制到d盘,并且实现一部分一部分读取,一部分一部分写入d盘,需要读取c盘文件,写:到d盘

4.其他模式:r+,w+,a+  +:扩展

一个文件:要么读,要么写,

r+:表示读写操作,偏向于读,先读后写,用的最多的是r+.

w+:写读操作,先写后读,写完后,光标在最后,要想读,需要光标移到开头

a+:追加写读操作,在最后写,与光标位置无关.

例:w+

f=open("电影",mode="w+",encoding="utf-8")
f.write("我不是药神,怎么了")
print(f.read())#是空的
f.flush()
f.close()

不能读到内容,加上f.seek(0)

f=open("电影",mode="w+",encoding="utf-8")
f.write("我不是药神,怎么了")
f.seek(0)
print(f.read())#我不是药神,怎么了
f.flush()
f.close()

例:r+  #这个依然无法创建文件

f=open("电影",mode="r+",encoding="utf-8")
f.write("鬼子来了")
f.seek(0)
print(f.read())#鬼子来了神,怎么了
f.flush()
f.close()

先读后写,先读了”我不是药神”,然后写入了”鬼子来了”,最后结果就是”鬼子来了神,怎么了”

5.其他模式:r+b  w+b a+b 操作的是字节.

(三)文件的修改操作(这是比较难的)

先建一个文件

(1)把文件中的大帅哥,改成”dsb”

第一步:先读取文件,然后建一个副本,把修改的内容放到副本.通过for line 在源文件读取内容,然后进行修改,再写入副本中.

f=open("老男孩",mode="r",encoding="utf-8")
f2=open("老男孩_副本",mode="w+",encoding="utf-8")
for line in f:
    s =line.replace("大帅哥","dsb")
    print(s)
    f2.write(s)
f.close()
f2.flush()
f2.close()

第二部:删除原文件:引入os文件(操作系统文件)

第三步把副本文件的名字改成原文件名字.

import os
f=open("老男孩",mode="r",encoding="utf-8")
f2=open("老男孩_副本",mode="w+",encoding="utf-8")
for line in f:
    s =line.replace("大帅哥","dsb")
    f2.write(s)
#删除源文件,给副本改本名
f.close()
f2.flush()
f2.close()
os.remove("老男孩")
os.rename("老男孩_副本","老男孩")

第四步:把速度放慢,import time

time.sleep(5)#暂停5s

import os
import time
f=open("老男孩",mode="r",encoding="utf-8")
f2=open("老男孩_副本",mode="w+",encoding="utf-8")
for line in f:
    s =line.replace("大帅哥","dsb")
    f2.write(s)
#删除源文件,给副本改本名
f.close()
f2.flush()
f2.close()
#暂停5s
time.sleep(5)
os.remove("老男孩")
time.sleep(5)
os.rename("老男孩_副本","老男孩")

(四)对于f.close和f.flush,替代的方式

with open("老男孩",mode="r",encoding="utf-8") as f:
    with open("老男孩_副本",mode="w",encoding="utf-8") as f2:

(五)文件操作的补充

(1)seek的两个内部定义

f.seek(0)=f.seek(0,0)光标移动到开头,后面的0可以省略.

f.seek(0,2)光标移动到末尾 

f.seek(0,1)表示光标当前位置

f.seek(2,1)#表示当前位置往前走2个

f.seek(2,0)#开头处往前走两个位置.

(2)f.tell()#告诉当前光标的位置,光标的单位是字节.

比如:

f=open("老男孩",mode="r",encoding="utf-8")
c=f.read(5)
print(c)#Alex是
print(f.tell())#7

#结果是7,utf-8中中文是三个字节.

 (3)f.truncate(7)#截取7个字节,如果不给参数,那就是从头截到光标所在地.

f=open("老男孩",mode="w",encoding="utf-8")
c=f.truncate()
b=f.truncate(7)
print(c)#0说明光标在开头
print(b)#7说明光标到7有7个字节
f.flush()
f.close()

(六)文件的读取练习

建立文件:fruit

fruit:
1,香蕉,3.99,20t 2,黄瓜,1.25,5t 3,桃子,10,6t 4,西瓜,8,1.6t

 如何保存,后面的人用如何方便

处理成大的列表

里面用字典表示:

方法一:

f=open("fruit",mode="r",encoding="utf-8")
result=[]
for line in f:
    lst=line.strip().split(",")
    fruit_list = {}
    fruit_list["序号:"]=lst[0]
    fruit_list["水果:"]=lst[1]
    fruit_list["单价:"]=lst[2]
    fruit_list["重量:"]=lst[3]
    print(fruit_list)
    result.append(fruit_list)
print(result)

f.flush()
f.close()

 方法二:通过字典的keys#这个方法更加智能化

f=open("fruit",mode="r",encoding="utf-8")
a=f.readline()
tit=a.strip().split(",")
# print(tit)#抬头的列表
result=[]
for line in f:
    lst=line.strip().split(",")
    # print(lst)
    dic={}
    for i in range(len(tit)):
        dic[tit[i]]=lst[i]
    result.append(dic)
print(result)

f.flush()
f.close()

 对于小型公司的日志文件就可以处理了.

(六)文件的路径:

(1)绝对路径比如c:/hyf.jpg,从磁盘根目录开始寻找.一般情况是不用的.因为调用的文件不一定在新的用户手上有.一般应用于固定的运营日志和备份,因为这些是固定的.

(2)相对路径:相对于当前文件所在的文件夹

比如:f=open("fruit",mode="r",encoding="utf-8")

该文件默认在当前程序所在位置.

  ../  #表示上一次文件夹

比如:f=open("../fruit",mode="r",encoding="utf-8")

二.函数

(一)函数的含义

例如:”约过么”的案例分析

 

每次想约,都需要重新调用上述代码:

如何实现想什么用,就用上述代码,这就是适用于函数,把上述代码封装,形成函数,然后再需要的时候,调用函数.

(二)如何定义一个函数 define#定义

def yue():
    print("1.打开手机")
    print("2.打开陌陌")
    print("3.找一个心意的她")
    print("4.聊一聊理想和人生")
    print("5.走啊,约起!!!")
yue()

#好处:一次声明,到处去调用

#函数名:和变量名是一致的,都要遵循变量#的命名规范.

#函数名就是变量名

#这个变量名可以被赋值

(三)函数可以有返回值

例如:返回值有3种

1.有一个返回值:return,表示返回值,应用最多

def yue():
    print("1.打开手机")
    print("2.打开陌陌")
    print("3.找一个心意的她")
    print("4.聊一聊理想和人生")
    print("5.走啊,约起!!!")
  return"胡一菲","谢冰清","今天"#接收的结果是: ('胡一菲', '谢冰清', '今天')
 ret=yue() print("接收的结果是:",ret)

#谁调用的函数值,返回给谁.

#return可以终止一个函数的执行

2.函数中没写return或者只写了return,返回的是none,终止函数.主要应用于这个函数是无效的,可以终止了.

3.返回多个结果时,此时调用方接受到的是元组.一般在别的语言中没有.

4.指定某一个工具去约

需要再yue(tools)

调用:yue(“微信”)  yue(“陌陌”)

def yue(tools,ta):
    print("1.打开手机")
    print("2.打开%s"%tools)
    print("3.找一个心意的%s"%ta)
    print("4.聊一聊理想和人生")
    print("5.走啊,约起!!!")
    return"胡一菲","谢冰清","今天"#接收的结果是: ('胡一菲', '谢冰清', '今天')
ret=yue("微信","")
ret=yue("陌陌","")
print("接收的结果是:",ret)

 还可以传递,年龄\身高等

5.参数:在函数执行的时候函数传递的信息

    (1)形参:在函数声明的位置的变量

    (2)实参:在函数调用的位置给出的具体的数据.

    (3)传参:把实参传递给形参的过程.

可以应用在计算机中.

6.应用:给函数传递两个数据a,b.计算a+b的结果.

a=int(input("请输入第一个数字:"))
b=int(input("请输入第二个数字:"))
def fun(a,b):
    return a+b
ret=fun(a,b)
print(ret)

 两个参数:一个原文件,一个目标地址

def copy(src,target):
    f1=open(src,mode="rb")
    f2=open(target,mode="wb")
    for line in f1:
        f2.write(line)
    print("复制成功!")
copy("C:\untitled\day03","C:\untitled")

 与内置函数len()没有区别.

8.参数:在函数执行的时候函数传递的信息

(1)形参:在函数声明的位置的变量

    1)按照位置声明变量

   2)按照默认值输入:在形参的位置给出默认值,当不给传送值时,默认生效.

主要应用于大多数是北京工作,大多数男生,那么就可以设置默认值参数:gender=”男”,job_address=”北京”

def reg(name,age,gender="",location="北京"):
    print(name,age,gender,location)
reg("小二",23)
reg("今天",24,"","上海")
reg("明天",24)

3)位置在前,默认值在后.

4)位置参数的动态传参*food(单独一个*表示语法,后面的food,才是参数,接收到的是一个元组.)

    比如:吃货和妹子的吃的多少不一样,需要删增参数,可以使用动态传参

def chi(*foods):
    print(foods)
chi("大米","鱼香肉丝")
chi("","馒头","烤鱼")

5)关键字动态传参**food(两个**接收关键字参数,food是形参)

def chi(**foods):
    print(foods)
chi(pre="大米",fu="窝窝头",soup="蛋花汤")#{'pre': '大米', 'fu': '窝窝头', 'soup': '蛋花汤'}

6)形参的声明顺序:

位置->*arges-> 默认值->**kyarges

    以上参数顺序可以任意使用,但是顺序必须

是这个顺序.

例:位置>*arges

只有写上a=6,a才能接收参数.

例:默认值和*arges

#默认值5,没有生效,如何让默认值生效,只能把3,4,5删除,c=5,才能生效,而*arges就没有效果了.

如果实参里面不用关键字,c一定生效.

(6)万能参数:可以接受所有的参数,无敌传参

例:print的调研,前面是位置参数,后面的sep是关键字.

(2)实参:在函数调用的位置给出的具体的数据.

1)位置参数:按照形参的声明顺序给形参传递信息.

 

不给,或者给出的参数多了也会报错.

2)关键字参数:按照形参上面的变量名制定参数,可以打乱顺序.

3)混合参数:位置+关键字,有顺序的问题.

#位置在前,关键字在后,是正确用法.

#关键字在前,位置在后,就会报错.

(3)传参:把实参传递给形参的过程.

可以应用在计算机中.

(4)*和**:在形参位置相对于聚合的作用,聚合成元组或字典.在实参位置相当于打散.

例如:位置参数和关键字参数

ef chi(*foods):
    print(foods)
chi("","馒头","烤鱼","烤串","蔬菜")#('粥', '馒头', '烤鱼', '烤串', '蔬菜')
food=['', '馒头', '烤鱼', '烤串', '蔬菜']
chi(*food)

三.名称空间

你创建的变量\函数\类\对象都会有独立的内存空间

(1)内置名称空间

(2)全局名称空间

(3)局部名称空间

1.内置名称空间:Python内存命名的一些内容,print,input,len

2.全局内存空间:在.py文件中,定格写的都是全局内存空间,全局都能用,必须在内置名称空间之后.

3.局部名称空间:你的函数(类)内部 声明的变量

神坑1:注意下面全局名称空间

 

能打印c,不能打印b,

C是全局名称空间,而b局部名称空间

这个c也是全局的.

4.内部\全局\局部的关系

5.寻找顺序:在局部找,然后全局,然后内置.

因此,局部查出的优先级最高.

四.作用域:你的变量可以作用的范围

1.全局作用域:一般由两个空间:内置+全局空间.

2.局部作用域:只能是局部

例1:如全局作用域,和查看内置作用域

 

例2:局部作用域#pass为了语法的完整,

打印结果中没有a=50.说明a=50 不是全局的.

例3:全局和局部作用域的明显区别:

:a=10和a=20,是完全没关系的

打印结果:10 20 10

例4:func2,先在func2中找,没有再去全局找,不会再func1中找.

结果:20 10

3.locals#查看当前的名称空间,放在全局是全局,放在局部是局部.

globals()#永远打印的全局的,放在哪都是全局.

五.函数的嵌套

1.inner的作用域是outer,在外边不能用inner

 

2.函数中套另一个函数.

#可以调用inner 111

3.判断下面的打印顺序

打印结果结果就是:555,1111,222,呵呵呵,333,4444.

4.函数的互相调用.

六.global和nonlocal

#global

1.当局部作用域没有a,但是要用a,只能去全局找.

2.Python中不能用局部改变全局的量,如在加上a+=1,使用的全局的a,而全局的a=10,不能再局部改变.

 

3.在局部改全局是很危险的事项,有些情况不得不改.把全局变量拽到局部.即:global a 就是把全局a拽到局部.这样也改变了全局变量.

#nonlocal

1.把离他最近的那一层的局部变量,引入进来.

这个程序只能用nonlocal,不能用global

2.nonlocal不能拿全局的变量

 

猜你喜欢

转载自www.cnblogs.com/kenments/p/10276718.html