Python 小栈_11:Python 函数闭包与装饰器

今日所学:

一、装饰器

1、定义:装饰器本质上就是一个函数。功能是为其他函数添加附加功能。

2、两大原则:

(1)不修改被修饰函数的源代码;

(2)不修改被修饰函数的调用方式。

即被修饰的函数原来是什么样,就是什么样。

3、装饰器的知识储备:

装饰器=高阶函数+函数嵌套+闭包

4、装饰器的框架:

def foo():
    def wrapper(func):
        print(func)
        func()
    return wrapper

二、高阶函数

满足以下任意一个条件即为高阶函数:

1、函数接收的参数是一个函数名;

2、函数的返回值是一个函数名。


高阶函数1:函数接收的参数是一个函数 可以实现不改变函数的源代码,但改变了函数的调用方式 import time def foo(): time.sleep(3) print("你好啊林师傅") def test(func): start_time=time.time() func() stop_time=time.time() print("函数运行时间为%s"%(stop_time-start_time)) test(foo)--->foo()

>>>

    你好啊林师傅
    函数运行时间为3.0016891956329346


高阶函数2.return的值为一个函数名,可以不更改函数的调用方式
def foo(): print("你好啊林师傅") def test(func): return func foo=test(foo) foo()

>>>

     你好啊林师傅
     函数运行时间为3.000659227371216
     你好啊林师傅

 

两者结合:可以实现功能,但多运行了一步
import time def foo(): time.sleep(3) print("你好啊林师傅") def test(func): start_time = time.time() func() stop_time=time.time() print("函数运行时间为%s"%(stop_time-start_time)) return func foo=test(foo) foo()

>>>

      你好啊林师傅
      函数运行时间为3.000659227371216
      你好啊林师傅

三、函数嵌套和闭包

函数嵌套:即在函数的里面再嵌套一个函数,一层层的嵌套。

闭包:即封装我们的变量,闭包是融合在函数嵌套里面的。


函数嵌套:函数里面再定义一个函数,一层层嵌套 闭包:用来封装变量,类似作用域
def father(name): print("我是%s"%name) def son(): print("%s是我的爸爸"%name) def grandson(): name="happy" print("%s是我的爷爷"%name) grandson() son() father("banana")

>>>

       我是banana
       banana是我的爸爸
       happy是我的爷爷

四、装饰器整体实现和完善

装饰器实现——
import time def timmer(func): def wrapper(): start_time=time.time() func() stop_time=time.time() print("函数运行时间为%s"%(stop_time-start_time)) return wrapper @timmer #这一步相当于test=timmer(test) def test(): time.sleep(3) print("我是你好") # test=timmer(test) test()
两种完善——

1、装饰器加入返回值
import time def timmer(func): def wrapper(): start_time=time.time() res=func() stop_time=time.time() print("函数运行时间为%s"%(stop_time-start_time)) return res return wrapper @timmer #这一步相当于test=timmer(test) def test(): time.sleep(3) print("我是你好") return '这是test的返回值' # test=timmer(test) res=test() print(res)

2、装饰器加入参数
import time def timmer(func): def wrapper(*args,**kwargs): --->args=("alxe",18),kwargs={} start_time=time.time() res=func(*args,**kwargs) --->*args=*("alxe",18),**kwargs=**{}当有两个参数时,会自动解析序列,一一对应赋予参数。多一少一都不行 stop_time=time.time() print("函数运行时间为%s"%(stop_time-start_time)) return res return wrapper @timmer #这一步相当于test=timmer(test) def test(name,age): time.sleep(3) print("我是[%s],年龄是[%s]"%(name,age)) return '这是test的返回值' # test=timmer(test) res=test("alex",18) print(res)

五、实现认证功能


1、实现验证功能:
current_dic
={"username":None,"login":False} def test(func): def wrapper(*args,**kwargs): if current_dic["username"] and current_dic["login"]: res=func(*args,**kwargs) return res username=input("用户名为: ").strip() passwd=input("密码为: ").strip() if username=="alex" and passwd=="123": current_dic["username"]=username current_dic["login"]=True res = func(*args, **kwargs) return res else: print("用户名或者密码错误") return wrapper @test def index(): print("欢迎来到京东主页") @test def home(name): print("欢迎[%s]回家"%name) @test def shopping_car(name): print("[%s]的购物车里有[%s,%s,%s]"%(name,"衣服","","鞋子")) index() home("happy") shopping_car("happy")

  缺点:用户需一次次输入验证名字和密码。


2、实现从一个固定列表中获取用户信息的验证登陆
current_dic
={"username":None,"login":False} #全局变量,用来保存用户登陆的状态 name_list=[ #用户的列表 {"username":"happy","passwd":"123"}, {"username":"bananna","passwd":"123"}, {"username":"cat","passwd":"123"}, {"username":"hoilday","passwd":"123"} ] def test(func): def wrapper(*args,**kwargs): if current_dic["username"] and current_dic["login"]: #判断用户是否已经登陆,是的话就直接执行函数 res=func(*args,**kwargs) return res username=input("用户名为: ").strip() #若用户还没登陆,则让用户输入登陆信息 passwd=input("密码为: ").strip() for username_dict in name_list: #循环列表,循环出的是一个个字典 if username==username_dict["username"] and passwd==username_dict["passwd"]: current_dic["username"]=username #登陆一次后就要把用户状态跟着改过来 current_dic["login"]=True res = func(*args, **kwargs) #执行函数 return res else: #这里若else再tab一个位置,则就变成了没循坏一次没有就直接报错,这是不对的。 print("用户名或者密码错误") #要把列表中所有的元素皆循环一遍后再告知是否是输入错误。 return wrapper @test def index(): print("欢迎来到京东主页") @test def home(name): print("欢迎[%s]回家"%name) @test def shopping_car(name): print("[%s]的购物车里有[%s,%s,%s]"%(name,"衣服","","鞋子")) index() home("happy") shopping_car("happy")

缺点:固定从一个列表中获取用户信息,且认证方式只有一种。


3、实现以不同的认证方式进行认证登陆

current_dic={"username":None,"login":False} def test_auth(auth_type="filedp"): #在最外层加入新的参数,则嵌套的函数都会接收到这个值 def test(func): def wrapper(*args,**kwargs): if auth_type=="filedp": #一种验证方式 if current_dic["username"] and current_dic["login"]: res=func(*args,**kwargs) return res username=input("用户名为: ").strip() passwd=input("密码为: ").strip() if username=="happy" and passwd=="123": current_dic["username"]=username current_dic["login"]=True res = func(*args, **kwargs) return res else: print("用户名或者密码错误") if auth_type=="ldap": #一种验证方式 print("系统正在维修,请使用filedp方式进行认证") if auth_type=="ssss": #一种验证方式 print("系统正在维修,请使用filedp方式进行认证") return wrapper return test @test_auth(auth_type="filedp") #这里test_auth(auth_type="filedp")=test() index=test(index) def index(): print("欢迎来到京东主页") @test_auth(auth_type="ldap") def home(name): print("欢迎[%s]回家"%name) @test_auth(auth_type="ssss") def shopping_car(name): print("[%s]的购物车里有[%s,%s,%s]"%(name,"衣服","","鞋子")) index() home("happy") shopping_car("happy")


总结:第三种最终实现以不同种的认证方式进行认证登陆。可从文件、数据库或其他地方获取认证信息。

以上。

猜你喜欢

转载自www.cnblogs.com/211293dlam/p/12497922.html