文件处理和函数

文件处理和函数

文件处理

  • 读编码后的字符串
f = open("filename",mode = "r" ,encoding = "utf-8")
date = f.read() #一次读取文件所有内容,将操作文件的光标移动到最后
f.seek(0)#将操作文件的光标移动到最开始
date_line = f.readlines()#一次读取所有文件,返回值是一个文件包含所有行的列表
f.tell()# 显示现在操作文件的光标的位置
f.seek(0)
date_list = f.readlines()#一次读取一行,遇到\r或者\n为止
trun = f.truncate(3) #第三个字节后的内容全部删除
f.close()#关闭文件
  • 读二进制
f = open("filename",mode = "rb")
date =  f.read()
f.close()

  • 写字符串
f = open("filename","w",encoding = "utf-8")
date = "some date"
iterable_date = [str(i) + "\n" for i in range(10)]
f.write(date) #写入数据
f.writelines(iterable_date) #用于向文件中写入由迭代对象产生的一序列的字符串,如一个字符串列表,列表中需要加换行符。
f.flush() #强制将内存中的数据写入到磁盘
f.close()
  • 写二进制
f = open("filename",'wb',encoding = "utf-8")
f.write("some data")
f.close()

混合模式

  • 读写模式
with open("somefile","r+",encoding="utf-8") as f:#with内的代码块执行完后会自动关闭
	f.readable()#True
	f.writable()#True
	f.read()#将操作文件的光标移动到最后
	date = "some date \n"
	f.write(date)

在用r+模式写文件时要先把操作文件的光标移到最后,不然会覆盖原来文件内存在的内容。而且要自己手动加上换行,不然不会换行。

  • 写读模式
with open("somefile","w+",encoding = "utf8") as f:
    f.readable()#True
    f.writable()#True
    date = f.read()
    print(date)#这里date是空字符串,因为是先读的,和读模式一样,文件的内容已经被清空了。
    f.write("2333")# 此处光标移到了最后
   	f.tell()#返回值为4
    f.seek(0)#光标移到最开始
    print(f.read()) #此处打印的是2333

​ 在用w+模式是要注意,他是会清空文件的。所以应该在需要新建文件而且需要读内存中的数据的时候使用。

​ 在读取写入内存的数据时,要先把光标移动到开始的位置。

追加

with open("somefile",'a',encoding = "utf-8") as f:
    f.readable()#False
    f.writable()#True
    f.tell()# 返回的是值显示光标在文件末尾
    date = "\nsome date"
    f.write(date)

追加模式只能写不能读,而且默认光标位置在文件的最后。

修改

  • 新建一个文件,在这个文件中修改然后将这个文件重命名成原来的文件
import os
with open("file",'r',encoding = "utf8") as f_old:
    with open("file.bak",'w',encoding = "utf8") as f_new:
        for line in f_old:
            if old_str in line:
                line.replace(old_str,new_str)
            f_new.write(line)
os.rename("file.bak","file")
  • 在内存中修改然后w模式写到原文件
with open("file","r+",encoding = "utf-8") as f_old:
    date = f_old.readlines()
    for index,item in enumerate(date):
        if old_str in item:
            date[index] = item.replace("old_str","new_str")
    f_old.seek(0)
    f_old.writelines(date)
    f_old.truncate(f_old.tell())

函数

参数与返回值

形参变量

只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

实参

可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
在这里插入图片描述

  • 默认参数
def stu_register(name,age,country,course):
    print("----注册学生信息------")
    print("姓名:",name)
    print("age:",age)
    print("国籍:",country)
    print("课程:",course)

stu_register("王山炮",22,"CN","python_devops")
stu_register("张叫春",21,"CN","linux")
stu_register("刘老根",25,"CN","linux")

发现 country 这个参数 基本都 是"CN", 就像我们在网站上注册用户,像国籍这种信息,你不填写,默认就会是 中国, 这就是通过默认参数实现的,把country变成默认参数非常简单

def stu_register(name,age,country="CN",course):

这样,这个参数在调用时不指定,那默认就是CN,指定了的话,就用你指定的值。

  • 关键参数
    正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后
def stu_register(name, age, course='PY' ,country='CN'):
    print("----注册学生信息------")
    print("姓名:", name)
    print("age:", age)
    print("国籍:", country)
    print("课程:", course)

调用可以这样

stu_register("王山炮",course='PY', age=22,country='JP' )

但绝不可以这样

stu_register("王山炮",course='PY',22,country='JP' )

当然这样也不行

stu_register("王山炮",22,age=25,country='JP' )

这样相当于给age赋值2次,会报错!

  • 非固定参数

    • args
      如果不确定需要传入的位置参数的数量,就可以用
      args接收多个原来未定义的位置参数。
      eg.
    def send_message(sender,*args):
        for name in args:
            print("{} send to {}".format(email,name))
    send_email("alex","micheal","tom","maria")
    #执行结果
    alxa send to micheal
    alxa send to tom 
    alxa send to maria
    

    这里的*args是一个接收了除了第一个位置参数sender外的所有位置参数的元祖(“micheal”,“tom”,“maria”)
    如果想要给函数传一个列表,如果直接传:

    send_email("alxa",["micheal","tom","maria"])
    

    这时候的*args=([“micheal”,“tom”,“maria”],),传进去的列表是这个元祖的第一个元素
    传一个列表需要这样传

    send_email("alxa",*["micheal","tom","maria"])
    
    • **kwargs
      如果想要给函数传入未定义的关键参数就需要**kwargs
    def display_info(company, *args, **kwargs):
        print(company.center(20,"*"))
        for key,value in kwargs:
            print(key,value)
    display_info("Luffy",name = "alex", age = 22, addr = "Beijin")
    

    程序的运行效果:

在这里插入图片描述

这里的kwargs={“name”:“alex”,“age”:22,“addr”:“Beijing”}
如果想要直接给函数传一个字典

display_info("Luffy",{"name":"alex","age":22,"addr":"Beijing"})
#这里的args=({"name":"alex","age":22,"addr":"Beijing"},),kwargs={},不能这样传
#想要把字典传进去,需要这样传
display_info("Luffy",**{"name":"alex","age":22,"addr":"Beijing"})
  • 返回值
    函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回
    注意
    函数在执行过程中只要遇到return语句,就会停止执行并返回结果,所以也可以理解为 return 语句代表着函数的结束
    如果未在函数中指定return,那这个函数的返回值为None

函数中的变量

  • 局部变量和全局变量
    在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
    全局变量作用域是整个程序,局部变量作用域是定义该变量的函数。
    当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。
name = "Micheal"
def display_info():
	print(name)
	name = "Tom"
	print(name)

display_info()
print(name)

运行结果

Micheal# 内部未定义name,此处打印的是全局变量
Tom    # 内部定义了一个局部的变量,打印的是局部变量
Micheal# 函数内部修改的只是局部变量,并不会修改全局变量

如果想修改全局变量需要用到global

name = "Micheal"
def display_info():
	global name #函数内部声明name是全局变量
	print(name)
	name = "Tom"
	print(name)

display_info()
print(name)

运行结果

Micheal #打印的是全局变量
Tom		#由于函数内部声明了name为全局变量,此处打印的是全局变量name
Tom		#全局变量已被修改

global name的作用就是要在函数里声明全局变量name ,意味着最上面的name = "Micheal"即使不写,程序最后面的print也可以打印name

  • 函数中修改列表数据
    字符串是不可变数据类型,所以要声明全局变量。如果是可变数据类型,比如列表,字典 就算不声明全局变量。在函数内部修改,外边的列表也会改变
name = ["Alex","Tom","Micheal"]
def change_name():
    name.pop()
    print(name)
change_name()
print(name)

运行结果

["Alex", "Tom"]
["Alex","Tom" ]
  • 函数嵌套

  • 命名空间
    又名name space, 顾名思义就是存放名字的地方,存什么名字呢?举例说明,若变量x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方

名称空间共3种,分别如下

  1. locals: 是函数内的名称空间,包括局部变量和形参
  2. globals: 全局变量,函数定义所在模块的名字空间
  3. builtins: 内置模块的名字空间
    不同变量的作用域不同就是由这个变量所在的命名空间决定的。

作用域即范围

全局范围:全局存活,全局有效
局部范围:临时存活,局部有效
查看作用域方法 globals(),locals()

  • 作用域
  • 作用域的查找顺序
    问题:在inner()里的打印的n的值是多少?

LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> builtins

  1. locals 是函数内的名字空间,包括局部变量和形参
  2. enclosing 外部嵌套函数的名字空间
  3. globals 全局变量,函数定义所在模块的名字空间
  4. builtins 内置模块的名字空间

装饰器

装饰器: 本质就是函数,功能是为其他函数添加附加功能

原则:

  1. 不修改被修饰函数的源代码
  2. 不修改被装饰函数的调用方法
  • 高阶函数
    变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

    只需满足以下任意一个条件,即是高阶函数

    • 接受一个或多个函数作为输入
    • return 返回另外一个函数
  • 闭包
    关于闭包,即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响。

def outer():
    name = 'alex'

    def inner():
        print("在inner里打印外层函数的变量",name)

    return inner


f = outer() 

f()

**闭包的意义:**返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

  • 装饰器
装饰器和被装饰函数都无参数

一个计算函数运行时间的装饰器

import time
import random 
def stime(func):
    def wapper():
        start = time.time()
        func()
        stop = time.time()
        print(stop - start)
    return wapper
@stime
def helloworld():
	time.sleep(random.randint(0,3))
    print('helloworld')

helloworld()
被装饰的函数有参数
import time
import random 

def stime(func):
    def wapper(*args,**kwargs):
        start = time.time()
        res = func(*args,**kwargs)#与上一个的区别
        stop = time.time()
        print(stop - start)
    return wapper
    
@stime
def helloworld(name):
    time.sleep(random.randint(0,3))
    print('hello %s'%name)

helloworld('alxe')

eg.为函数添加验证是否登陆的装饰器

user_list = [
    {'name':'alxa','passwd':'123'},
    {'name':'micheal','passwd':'564'},
    {'name':'join','passwd':'789'}
]

logined_list = {'name':'None','login':None}
def loging_confire(func):
    def wapper(*args,**kwargs):
        if logined_list['login']:
            res = func(*args,**kwargs)
            return res
        else:
            username = input('please input your username')
            passwd = input('please input your user name')
            for name_dict in user_list:
                if username == name_dict['name'] and passwd == name_dict['passwd']:
                    logined_list['name'] = username.strip()
                    logined_list['login'] = passwd
                    res = func(*args,**kwargs)
                    return res
            else:
                print('your name or password is error, please try again later')
    return wapper


@loging_confire#相当于home = loging_confire
def home():
    print("this is your home page")

    
@loging_confire
def index():
    print("this is your index page")

    
print('before',logined_list)
home()
print('after',logined_list)
index()
装饰器和被装饰的函数都有参数

在flask中实现装饰器,根据用户角色控制路由的访问。

from flask import abort
from flask_login import current_user
from functools import wraps
from simpledu.models import User

def role_required(role):
    """ 带参数的装饰器,可以使用它保护一个路由处理函数只能被特定
    角色的用户访问:

        @role_required(User.ADMIN)
        def admin():
            pass
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwrargs):
            # 未登录用户或者角色不满足引发 404
            # 为什么不是 403?因为不希望把路由暴露给不具有权限的用户
            if not current_user.is_authenticated or current_user.role < role:
                abort(404)
            return func(*args, **kwrargs)
        return wrapper
    return decorator

# 特定角色的装饰器
staff_required = role_required(User.ROLE_STAFF)#这里的staff_required 和 admin_required都是内存地址
admin_required = role_required(User.ROLE_ADMIN)

@role_required(User.ROLE_STAFF) #等价于 test_func = role_required(User.ROLE_STAFF)(test_func) 
def test_func(*args,**kwargs):
	return "test func"

递归

匿名函数

匿名函数就是不需要显式的指定函数名的函数,用处很多。比如在map,reduce,filter需要传入函数时候传入,用的时候生成 不会占用程序内存资源。
匿名函数可以有多个参数但是只能有一个返回值

生成器和迭代器

内置函数

其他知识

三元运算

三元运算又称为三目运算是对简单条件语句的简写

eg.

a = 3
b = 5
c = a if a>b else b# c = 5
#和下面的写法作用一样
if a>b:
    c = a
else:
    c = b

列表生成式和字典生成式

列表生成式
#定义一个列表
l = [1,2,3,4,5,6]
#对列表里的每一个元素进行加一操作
#方法一,for循环迭代
for index,value in enumerate(l):
    l[index] += 1
#方法二,map函数
l = list(map(lambda x:x+1 ,l))
# 方法三,列表生成式
l = [i+1 for i in l]

map和filter函数能做的列表生成式都能做
eg.

  • filter
 l = [1,2,3,4,5,6,7,8,9]
 #取出所有的偶数
 # filter
l = list(filter(lambda x:x%2 == 0,l))
 # 列表生成式
l = [i for i in l if i%2 == 0]
  • map
l = [1,2,3,4,5,6,7,8]
# 每个列表中的元素都平方
# 方法一 列表生成式
l = list(map(lambda x:x**2,l))
#方法二 map函数
l = [i**2 for i in l]
  • 列表中使用三元运算符
l = [1,2,3,4,5,6,7]
# 列表中的元素大于3的都加一
l = [i+1 if i >3 else i for i in l]

字典生成式

# 生成一个有默认值的字典
dic = {i:"2333" for i in ["apple","banana","orange"]}
# 也可以用formkeys实现
dic = dict.fromkeys(["apple","banana","orange"],"2333")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值