函数和常用模块1 装饰器
主要内容
- 装饰器的定义
- 装饰器的重要性
- 装饰器的原则
- 装饰器理解以及操作
装饰器的定义
本质是函数。(装饰其他函数) 它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。
装饰器的重要性
比如:已经上线的生产环境上有100个函数,需要增加新功能,新增功能不能修改源代码,也不能修改原函数的,这个时候就用到了装饰器。
装饰器经常有切面需求的场景,比如:插入日志,性能测试,事务处理,缓存,权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。 概括的讲,装饰的作用就是为已经存在的对象添加额外的功能。
例子:
import time
def timmer(func):
def warpper(*args,**kwargs):
start_time = time.time()
func()
stop_time = time.time()
print('the func run time os %s' %(stop_time-start_time))
return warpper()
@timmer
def test1():
time.sleep(3)
print('in the test1')
test1()
装饰器的原则
-
不能修改被装饰函数的源代码.
-
不能修改被装饰得函数的调用方式.
-
不修改返回结果.
装饰器都函数来说是透明的。
装饰器理解以及操作
函数即“变量”
def test():
pass

相当于将函数体赋值给test的变量。 变量直接调用变量名,函数是函数名调用 test='函数体' test()
例子1:

将foo()函数体放入房间,然后通过foo()这个门牌号调用函数体,函数体按顺序执行, 当执行到bar()时候,没有门牌号对应。
例子2:
def bar():
print('in the bar')
def foo():
print('in the foo')
bar()
foo()
#######
def foo():
print('in the foo')
bar()
def bar():
print('in the bar')
foo()
上面两个时没有区别的,上面即可正常执行。 函数先定义后调用。调用之前已经解释器解释过了。就能调用成功。 将def bar() def foo()看成函数体。
高阶函数
-
把一个函数名当做实参转给另外一个函数 (在不修改被装饰函数源代码的情况下为其添加功能)。
-
返回值中包含函数名(不修改函数的调用方式)。
-
例子. 把一个函数名当做实参转给另外一个函数

bar 相当于门牌号,调用内存地址。
import time
def bar():
time.sleep(3)
print('in the bar')
def test1(func):
start_time = time.time()
func() #run bar
stop_time = time.time()
print('the func run time is %s' %(stop_time-start_time))
test1(bar)
运行结果:
in the bar
the func run time is 3.0036139488220215
相对于装饰器,调用方式被改变了,这要是在生产环境上功能上是不允许的。
- 返回值中包含函数名 例如:
import time
def bar():
time.sleep(3)
print('in the bar')
def test2(func):
print(func)
return func
#print(test2(bar))
t=test2(bar)
t()
bar=test2(bar)
bar()
运行结果:
<function bar at 0x102519400>
in the bar
<function bar at 0x102519400>
in the bar
没有改变调用方式。
嵌套函数
顾名思义就是函数里面套函数。 函数嵌套,在一个函数体内用def定义而不是调用另外一个函数。
例如:
def foo():
print('in the foo')
def bar():
print('in the bar')
bar()
foo()
运行结果:
in the foo
in the bar
局部作用域和全局作用域
在函数外,一段代码最始开所赋值的变量,它可以被多个函数引用,这就是全局变量; 在函数内定义的变量名,只能被函数内部引用,不能在函数外引用这个变量名,这个变量的作用域就是局部的,也叫它为局部变量;
如果函数内的变量名与函数外的变量名相同,也不会发生冲突。好比下面这种情况:
x =0
def grandpa():
x=1
def dad():
x=2
def son():
x=3
print(x)
son()
dad()
grandpa()
运行结果为:
3
x = 0这个赋值语句所创建的变量X,作用域为全局变量; x = 3这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数son()内使用。
x = 2这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数dad()内使用。
x = 1这个赋值语句所创建的变量X,它的作用域则为局部变量,只能在函数grandpa()内使用。
尽管这两个变量名是相同的,但它的作用域为它们做了区分。作用域在某种程度上也可以起到防止程序中变量名冲突的作用,但如果做为玩蛇网python初学者来说,尽量避免这种情况发生比较好。
高阶函数+嵌套函数=》装饰器
简单装饰器例子
@语法糖
import time
def timer(func): #timer(test1) func=test1
def deco():
start_time = time.time()
func()
stop_time = time.time()
print('the func run time %s' % (stop_time - start_time))
return deco
@timer #timer(test1) func=test1
def test1():
time.sleep(3)
print('in the test1')
@timer
def test2():
time.sleep(3)
print('in the test2')
#test1=timer(test1) #返回的是deco的内存地址
test1() #相当于运行test1
#test2=timer(test2) #返回的是deco的内存地址
test2() #相当于运行test2
运行结果:
in the test1
the func run time 7.023896217346191
in the test2
the func run time 7.066271066665649
传参数的装饰器例子
import time
def timer(func): #timer(test1) func=test1
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs)
stop_time = time.time()
print('the func run time %s' % (stop_time - start_time))
return deco
@timer #test1= timer(test1)
def test1():
time.sleep(3)
print('in the test1')
@timer #test2=timer(test2) = deco test2(name)=deco(name)
def test2(name,age):
print('test2', name,age)
test1()
test2('cathy',22)
运行结果:
in the test1
the func run time 3.003638982772827
test2 cathy 22
the func run time 3.409385681152344e-05
用户验证场景装饰器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Cathy Wu
user,passwd='cathy','abc123'
def auth(auth_type):
print('auth fucn:',auth_type)
def outer_warpper(func):
def wrapper(*args, **kwargs):
print('wrapper func args:',*args, **kwargs)
if auth_type == 'local':
username = input('username:').strip()
password = input('password:').strip()
if user == username and passwd == password:
print('\033[32;1m User has passed authenticaiton\033[0m')
res = func(*args, **kwargs)
print('after authenticaiton')
return res
else:
exit('\033[32;1m Invalid passwodr or username\033[0m')
elif auth_type == 'ldap':
print('ldap authenticaiton')
return wrapper
return outer_warpper
def index():
print('welcome to the index')
@auth(auth_type='local')
def home():
print('welcome to the home')
return "from home"
@auth(auth_type='ldap')
def bbs():
print('welcome to the bbs')
index()
print(home())
bbs()
运行结果:
auth fucn: local
auth fucn: ldap
welcome to the index
wrapper func args:
username:cathy
password:abc123
User has passed authenticaiton
welcome to the home
after authenticaiton
from home
wrapper func args:
ldap authenticaiton
参考网页
http://www.cnblogs.com/alex3714/articles/5765046.html
http://egon09.blog.51cto.com/9161406/1836763
http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html

浙公网安备 33010602011771号