03---python基础(三)(文件操作--函数初识--闭包)

文件操作

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
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值