python函数下篇装饰器和闭包,外加作用域
函数是第一类对象
函数能够被当做对象传递,函数可以被赋值
装饰器和闭包的基础概念
装饰器是一种设计模式能实现代码重用,经常用于查日志,性能测试,事务处理等,抽离函数大量不必的功能。 装饰器:
1、装饰器本身是一个函数,用于装饰其它函数:
2、功能:增强被装饰函数的功能。
装饰器需要遵循的原则
1.不修改被装饰函数的源代码(开放封闭原则) 2.为被装饰函数添加新功能后,不修改被装饰函数的调用方式
装饰器 = 高阶函数+函数嵌套+闭包
高阶函数
1.函数接受的参数是一个函数名 2.函数的返回值是一个函数名 3.只有上述条件满足一个就是高阶函数
def foo(): print('高阶函数实例,被调用的函数') def func(foo): print('调用上面的函数') foo() func(foo)
把函数名当做参数传给高阶函数,高阶函数直接返回函数名
import time def foo(): print('from the foo') def timmer(func): start_time = time.time() return func stop_time = time.time() print('函数%s运行时间是%s')%(func,stop_time - start_time) foo = timmer(foo) foo()
高阶函数总结 1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
嵌套函数
def father(name): print('from father %s'%name) def son(): print('from son') def grandson(): print('from grandson') grandson() son() father('逗逼')
闭包函数:函数在嵌套环境中,如果在内层函数里,对外层函数作用域中的变量进行引用,在外层函数返回后内层函数依然可以使用外层函数中的变量,这种变量就构成了内层函数可以使用的环境。所以闭包对隐藏状态,以及在函数对象和作用域中随意切换,一个函数可以发挥N种功用
def f1(x): def f2(y): return y ** x return f2 f1(4) f3=f1(3) type(f3) f3(4) def startPos(m,n): def newPos(x,y): print(''The old position is (%d,%d), and the new position is (%d,%d)"%(m,n,m+x,n+y)) return newPos action = startPos(10,10) action(1,2) action(-1,3) #结果 <function f1.<locals>.f2 at 0x02125270> <class 'function'> 64 The old position is (10,10),and the new position is (11,12) The old position is (10,10),and the new position is (9,13)
无参装饰器
无参装饰器 = 高级函数 + 函数嵌套 基本框架
#这就是一个实现一个装饰器最基本的架子 def time(func): def wrapper(): func() return wrapper 加上参数 def timer(func): def wrapper(*args,**kwargs): func(*args,**kwargs) return wrapper 加上功能 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print('函数[%s],运行时间是[%s]'%(func,stop_time-start_time)) return wrapper 加上返回值 import time def timer(func): def wrapper(*args,**kwargs): start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print('函数[%s],运行时间是[%s]'%(func,stop_time-start_time)) return res return wrapper 使用装饰器 def cal(arry): res = 0 for in in array: res+=i return res cal = timer(cal) cal(range(10) 语法糖@ @timer def cal() def cal(array): res=0 for i in array: res+=i return res cal(range(10)) 有参装饰器 user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, ] current_user={'username':None,'login':False} def auth(auth_type='file'): def auth_deco(func): def wrapper(*args,**kwargs): if auth_type == 'file': if current_user['username'] and current_user['login']: res = func(*args,**kwargs) return res username = input('用户名:').strip() passwd = input('密码:').strip() for index,user_dic in enumerate(user_list): if username == user_dic['name'] and passwd ==username['passwd']: current_user['username'] =username current_user['login']=True res = func(*args,**kwargs) return res break else: print('用户名或者密码错误,重新登录') elif auth_type =='ldap': print('登录成功') res = func(*args,**kwargs) return res return wrapper return auth_deco @auth(auth_type='ldap') def index(): print('欢迎来到主页面') @auth(auth_type='ldap') def home(): print('家目录') def shopping_car(): print('购物车页面') def order(): print('订单页面') index() home()
作用域规则 每次执行执行一个函数时,就会创建新的局部命名空间。该命名空间代表一个局部环境,其中包含函数参数的名称和在函数体内赋值的变量名称。解析这些名称 时,解释器首先搜索局部命名空间、如何没有找到匹配的名称,它就会搜索全局命名空间。函数的全局命名空间始终是定义该函数的模块。如果解释器在全局命名空间中也找不到匹配值,最终会检查内置命名空间。如果仍然找不到,就会引发NameError异常