Python 之 装饰器
装饰器 中的“器”代指函数
所以装饰器本质是函数,用来装饰其它函数。例如:为其它函数添加其他功能
实现装饰器需要的知识: 高阶函数+嵌套函数 == 装饰器
1、函数就是“变量”
函数就是“变量”说的就是 函数在内存的存储和回收 和变量类似。
2、高阶函数(函数调用另一个函数,把函数名作为另一个函数的参数)
- def foo():
- print("foo ...")
- def fun(fun):
- print(fun)
- fun() # fun = foo 相当于foo 和 fun 所指的内存一样
- fun(foo)
- #结果 <function foo at 0x0000000003C6E8C8>
- # foo ...
我们发现 foo.. .执行了 ,是因为foo 和 fun 所指的内存一样 ,函数即变量 可以赋值
但是我们为什么要多此一举,这样执行呢? 来看下面代码:
- import time
- def foo():
- time.sleep(1)
- print("foo ...")
- def fun(fun):
- start_time = time.time()
- fun() # fun = foo 相当于foo 和 fun 所指的内存一样
- stop_time = time.time()
- print("cost time %s" %(stop_time - start_time))
- foo()
- fun(foo)
- #结果:foo ...
- # foo ...
- # cost time 1.0000572204589844
我们发现我们实现了装饰一个函数 我们执行 foo() 和 fun(foo) 效果不一样 ,fun装饰了 foo 函数
现在 我们已经满足了原则1 :不改变源代码
我们再看另一个函数:
- import time
- def bar():
- time.sleep(3)
- print('in the bar')
- def test2(func):
- print(func)
- return func
- print(test2(bar))
- print("------------------")
- bar=test2(bar)
- bar() #run bar
- #结果
- # <function bar at 0x0000000003C6E8C8>
- # <function bar at 0x0000000003C6E8C8>
- # ------------------
- # <function bar at 0x0000000003C6E8C8>
- # in the bar
我们满足了两个原则
3、嵌套函数
- def grandpa():
- # x=1
- def dad(): #只是定义阶段
- x=2
- def son(): #只是定义阶段
- x=3
- print (x)
- son() #必须在这个位置执行
- dad() #必须在这个位置执行 运行dad
- grandpa()
看下面的例子: 假如我们实际场景有100个函数(这里列举两个),这里的函数已经上线运行,现在需要为每一个函数增加一个日志。如果用下面的方式相当于修改了函数的源代码,万一产生错误那么后果很严重(业务崩溃)。
- __author__ = "WSX"
- def fun1():
- print("fun1")
- logger("")
- def fun2():
- print("fun2")
- logger("")
- def logger( fun):
- print("Logger %s" %fun)
- fun1()
- fun2()
所以函数一旦写好不要去修改函数源代码。
这里我们就需要装饰器。
装饰器的原则:
1、不会修改被修饰的函数源码
2、不要修改函数的调用方式
现在我们来写一个简单的装饰器:
- import time
- def timmer(func): #这是一个装饰器 ,计算时间
- def warpper(*args,**kwargs):
- start_time=time.time()
- func(*args,**kwargs)
- stop_time=time.time()
- print('the func run time is %s' %(stop_time-start_time))
- return warpper
- @timmer
- def test1():
- time.sleep(3)
- print('in the test1')
- test1()
- 结果:
in the test1- the func run time is 3.0001718997955322
上面的代码满足装饰器的原则。现在来分析程序:
- @timmer 相当于test1 = timmer(test1)
- 现在我们就完成了一个装饰器。timmer是装饰器 test1是需要被装饰的函数
- 下面是老男孩教育Alex写的复杂的带函数返回值的装饰器(堪称高潮):
- __author__ = "Alex Li"
- import time
- user,passwd = 'alex','abc123'
- def auth(auth_type):
- print("auth func:",auth_type)
- def outer_wrapper(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;1mUser has passed authentication\033[0m")
- res = func(*args, **kwargs) # from home
- print("---after authenticaion ")
- return res
- else:
- exit("\033[31;1mInvalid username or password\033[0m")
- elif auth_type == "ldap":
- print("搞毛线ldap,不会。。。。")
- return wrapper
- return outer_wrapper
- def index():
- print("welcome to index page")
- @auth(auth_type="local") # home = wrapper()
- def home():
- print("welcome to home page")
- return "from home"
- @auth(auth_type="ldap")
- def bbs():
- print("welcome to bbs page")
- index()
- print(home()) #wrapper()
- bbs()
- 采用三层嵌套,第二层用于返回需要被装饰的函数的返回值。
Python 之 装饰器的更多相关文章
- Python各式装饰器
Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...
- Python札记 -- 装饰器补充
本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...
- python基础——装饰器
python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...
- 【转】详解Python的装饰器
原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...
- 两个实用的Python的装饰器
两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...
- python 基础——装饰器
python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- python基础—装饰器
python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...
- 详解Python的装饰器
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
- 关于python的装饰器(初解)
在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...
随机推荐
- Solaris与Windows Active Directory集成
通过Solaris与Active Directory的集成,Solaris可以使用Windows 2003 R2/ 2008 Active Directory来进行用户登录验证.以下是简要配置过程. ...
- elastic(6) mget
转自:https://www.cnblogs.com/zhaijunming5/p/6424800.html GET /library/books/1 { "_index": &q ...
- css水平垂直居中方法(一)
第五种方法: 首先设置一个div,设置其的width与height,为了方便观察,我定义了div的背景色为red,代码如下: <!doctype html> <html lang=& ...
- cookie禁用后重定向跳转时session的跟踪
- 使用Aspectj 的配置文件方式进行aop操作
- isinstance判断某个对象是否是某个类创建的
#!/usr/bin/env python li = [11,22] #判断某个对象是否是某个类创建的. r = isinstance(li, list) print(r) 结果: C:\Python ...
- 使用git将代码传到github
廖雪峰git教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 注:add加入 ...
- SSM项目连接远程Linux服务器的mysql 启动tomcat卡在了 Initializing Spring root WebApplicationContext
网上查了原因, linux下mysql访问速度缓慢并且ssh连接缓慢的原因 解决办法: 1.linux ssh连接慢 最近发现ssh连接的时候却很慢,ping的速度非常好,让人误以为是ssh连接不上. ...
- 760. Find Anagram Mappings乱序字符串的坐标位置
[抄题]: Given two lists Aand B, and B is an anagram of A. B is an anagram of A means B is made by rand ...
- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at ExTestDrive.main ...