python基础day3

一、文件管理

文件管理是很多应用程序的基本功能和重要组成部分。Python可以使文件管理极其简单,特别是和其它语言相对比。

1.    读操作

1.1r模式

1.1.1读取其他路径下文件

首先在D盘创建一个123.txt的文件

f1 = open(r'D:\123.txt', encoding='utf-8', mode='r')  //r为转义后面的\
content = f1.read()      
print(content)
f1.close()                //读取后关闭文件,打开文件过多事出现Too many open files.
结果
123
456
789

1.1.2读取当前目录下文件

f1 = open('123', encoding='utf-8', mode='r')  r模式可不写,默认的就是r模式
content = f1.read()
print(content)
f1.close()

1.1.3read()全部读出

由1.1看出是读出文件的全部内容

1.1.4read(n)按照字符读取

f1 = open('123', encoding='utf-8', mode='r')
content = f1.read(5)
print(content)
f1.close()
结果:
1231

1.1.5readline()按行读取

readline每次读取一行

f1 = open('123', encoding='utf-8', mode='r')
print(f1.readline())
print(f1.readline())
print(f1.readline())
print(f1.readline())
f1.close()
结果:
1231
 
4567
 
123

1.1.5readlines() 将每一行作为列表的一个元素并返回这个列表

f1 = open('123', encoding='utf-8', mode='r')
print(f1.readlines())
f1.close()
结果
['1231\n', '4567\n', '123\n', '\n']

1.7for循环读取内容

f1 = open('123', encoding='utf-8', mode='r')
for i in f1:
    print(i)  //和按行读取类似
f1.close()
结果:
1231
 
4567
 
123

1.2rb模式

以bytes方式读取文件

非文字类的文件的操作。

unicode ---> bytes  encode()

bytes---> unicode  decode()

f1 = open('123',mode='rb')
print(f1.read())
f1.close()
结果:
b'1231\r\n4567\r\n123\r\n\r\n'   //其中的\n为换行符

1.3r+

r+为读写模式

f1 = open('123',mode='r+')
print(f1.read())
f1.write('666')
f1.close()
结果:
1231
4567
123   //这里没有读取操作,是因为光标的原因,读取操作,光标只会在123后面,无法读取到后添加的内容
 
测试先添加再读取
文件内容为
1
4567
123
 
 
f1 = open('123',mode='r+')
f1.write('666\n')
print(f1.read())
f1.close() 
结果:
67
123
 
文件内容为
666
67                        //可以看出添加再文件前,替换了三个字节,同样是光标导致
123

调整光标

f1 = open('123',mode='r+')
f1.seek(0,2)                       //光标移动到最后写入数据
f1.write('666')
f1.seek(0)                //光标移动到最前读取数据
print(f1.read())
f1.close()
结果:
1
4567
123666

2.    写操作

2.1w模式

f1 = open('log',encoding='utf8',mode='w')
f1.write("彭济昊是帅哥")
f1.close()

2.2w+读写

f1 = open('log',encoding='utf8',mode='w+')
print(f1.read())
f1.write("666")
f1.close()  //会覆盖之前的内容
结果:
文件中只有666

3.追加

3.1 a追加

f1 = open('log',encoding='utf8',mode='a')
f1.write("333")
f1.write("444")
f1.close()

结果

3.2a+追加读

f1 = open('log2', encoding='utf-8', mode='a+')
f1.write('123')
f1.seek(0)  //光标移动到最前
print(f1.read())
f1.close()
结果:
123

4其他文件操作

4.1显示指针位置

f1 = open('log', encoding='utf-8', mode='w')
f1.write('123456789')
print(f1.tell())
f1.close()
结果:
9
seek(参数),seek(0,2) 调至最后 按照字节去调整光标

4.2with文件操作

with open('log', encoding='utf-8') as f1,\
        open('log2', encoding='utf-8', mode='w')as f2:
    print(f1.read())
    f2.write('777')
结果:
123456789

查看log2

5.文件的改

文件的改的步骤

1,打开原文件,产生文件句柄。

2,创建新文件,产生文件句柄。

3,读取原文件,进行修改,写入新文件。

4,将原文件删除。

5,新文件重命名原文件。

import os                 //添加模块
with open('log', encoding='utf-8') as f1,\
    open('file_test.bak', encoding='utf-8', mode='w') as f2:
    for line in f1:
        line = line.replace('123','帅哥')  //把文件中的123修改为帅哥
        f2.write(line)
os.remove('log')
os.rename('file_test.bak','log')

查看文件

二、函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

2.1自建len函数

li = [1, 2, 3, 43, 'abc', 'pjh']
count = 0
for i in li:
    count += 1
print(count)              //由此可以实现和len类似的功能
 
把上述内容设置为函数,方便后续调用
def my_len():
    count = 0
    for i in li:  //次数只能指定固定的数字,和len还有些区别,应该把次数设置成变量
        count += 1
    print(count)
 
函数的形参和实参
 
 def my_len(a):  # 函数的定义()放的是形式参数,形参
     count = 0
     for i in a:
         count += 1
     return count
 ret = my_len(li)  # 函数的执行() 实际参数,实参
 print(ret)
 print(len(s1))  //此时len功能基本实现
 

2.2形参和实参介绍

从名字就可以看出,实参是一个实实在在存在的参数,是实际占用内存地址的,而形参只是意义上的一种参数,在定义的时候是不占内存地址的,如在上面例子中,a就是一个形参,s1是在调用函数时传入的一个实参,它的值被存储在形参a中。

函数的调用中,可能存在多个实参,在给函数传递参数的时候只要有两种方式,位置实参和关键字实参,每个实参都由变量名和值组成,实参还可以是列表、字典

2.2.1位置参数

位置参数。 必须一一对应,按顺序

def func1(x,y):
    print(x,y)
func1(1,2)
结果:
1 2

2.2.2默认参数

默认参数。 必须在位置参数后面

def register(name,sex='男'):
    with open('log',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)

2.2.3动态参数

*args,**kwargs 万能参数

*args 用来将参数打包成tuple给函数体调用

**kwarg用户将参数打包成字典给函数调用,其中键不需要引号

注意点:参数arg、*args、**kwargs三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)这个顺序,否则程序会报错 arg即为位置参数

def  fun(*args,**kwargs):
    print(args)
    print(kwargs)
fun(1,2,3,a="pjh",b='shuaige')
结果:
(1, 2, 3)
{'a': 'pjh', 'b': 'shuaige'}
 
 
 
def func1(*args,**kwargs):  # 函数的定义 * 聚合。
    print(args)
    print(kwargs)
l1 = [1,2,3,4]
l11 = (1,2,3,4)
l2 = ['alex','wusir',4]
func1(*l1,*l2,*l11)  # 函数的执行:* 打散功能。
func1(1,2,3,4,'alex','wusir',4,1,2,3,4)  # 函数的执行:* 打散功能。
dic1 = {'name1':'alex'}
dic2 = {'name2':'laonanhai'}
func1(**dic1,**dic2)               //没有**结果为元组中包含两个字典,只有一个*结果为元组中name1 name2
结果:
(1, 2, 3, 4, 'alex', 'wusir', 4, 1, 2, 3, 4)
{}
(1, 2, 3, 4, 'alex', 'wusir', 4, 1, 2, 3, 4)
{}
()
{'name1': 'alex', 'name2': 'laonanhai'}

三、函数的进阶

3.1全局变量和局部变量

我们通常把定义在函数外的变量成为全局变量,定义在函数内的变量称为局部变量,顾名思义,全局变量的作用域是整个代码段,局部变量的作用域就只是在它所属的代码段,变量只在它的作用域里有效

临时名称空间:临时名称空间,局部名称空间,存入函数里面的变量与值的关系,随着函数的执行结束,临时名称空间消失。

名称空间:全局名称空间,局部名称空间,内置名称空间。

作用域:

全局作用域:全局名称空间,内置名称空间。

局部作用域:局部名称空间

加载顺序,取值顺序。

加载顺序:内置名称空间 ----> 全局名称空间----> 局部名称空间(函数执行时)

取值顺序:局部名称空间 ---> 全局名称空间 ----> 内置名称空间

def fun():
    name = "pjh"           //name为局部变量。随着函数的关闭而消失
    print(name)
fun()
print(name)                        //提醒函数未定义
 
 
name1 = 'pjh'
age = 12
def func1():
    name1 = 'shuaige'
    age1 = 34
    print(name1)
func1()
print(name1)
结果:
shuaige                            //局部变量随着函数的关闭而消失
pjh

3.2global申明全局变量

def fun():
    global name
    name = "pjh"
    print(name)
fun()
print(name)
结果:
pjh
pjh               //没有随着函数的关闭而消失,而是成为全局变量
 

3.3nolocal

nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量

name1="peng"
def func1():
    name1 = 'pjh'
    print('+',name1)
    def inner():
        nonlocal name1
        name1= 'shuaige'
        print('*',name1)
        def inner1():
            print('-',name1)
        inner1()
    inner()
 
    print('%',name1)
func1()
print(name1)
结果:
+ pjh
* shuaige
- shuaige
% shuaige
peng
 
在函数内部的函数中调用了局部变量name1的值

3.2闭包

闭包 内层函数对外层函数非全局变量的引用,叫做闭包
闭包的好处:如果python 检测到闭包
他有一个机制,你的局部作用域不会随着函数的结束而结束

def wrapper():
    name1 = '老男孩'                //name1被内部函数inner调用
    def inner():
        print(name1)
    inner()
wrapper()
结果:
老男孩            
 
 
# 判断是不是闭包
name1 = 'pjh'
def wrapper():
    def inner():
        print(name1)
    inner()
    print(inner.__closure__)  # None
wrapper()
结果:
pjh
None             //None不是闭包
 
 
def wrapper():
    name1="pjh"
    def inner():
        print(name1)
    inner()
    print(inner.__closure__)  
wrapper()
结果:
pjh
(<cell at 0x000002026C4565E8: str object at 0x000002026C4F2960>,)  #为闭包
 
 
 

四、装饰器

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能

装饰器:在不改变原函数即原函数的调用的情况下,

为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等

import time
def timer(f1):  # f1 = func1
    def inner(*args,**kwargs):
        start_time = time.time()
        ret = f1(*args,**kwargs)  # func1()
        end_time = time.time()
        print('此函数的执行效率%s' %(end_time-start_time))
        return ret
    return inner @timer  # func1 = timer(func1)  inner
def func1(a,b):
    print(a,b)
    print('晚上回去吃烧烤....')
    time.sleep(1)
    return 666
ret2 = func1(111,222)  # inner(111,222)
print(ret2)
 
结果:
111 222
晚上回去吃烧烤....
此函数的执行效率1.0007083415985107
666
上一篇:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)


下一篇:eclipse 使用gradle构建系统时候报错