python装饰器介绍
"""
装饰器
定义:本质是函数(器:就是函数的意思),功能:装饰其他函数,就是为其他函数添加附加功能 原则:
1. 不能修改被装饰的函数的源代码
2. 不能修改被装饰的函数的调用方式 实现装饰器知识储备:
1. 函数即"变量"
2. 高阶函数
a: 把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
b: 返回值中包含函数名 (不修改函数的调用方式)
3. 嵌套函数 高阶函数 + 嵌套函数 --> 装饰器 参考链接:http://egon09.blog.51cto.com/9161406/1836763
""" # 将test1 和 test2 函数添加logging 功能 (未使用使用函数调用)
'''
def logger():
print ("logging") def test1():
pass
logger() def test2():
pass
logger() test1()
test2()
'''
# 装饰器示范_1
'''
import time def timmer(func):
def warpper(*args,**kwargs):
start_time = time.time()
func()
stop_time = time.time()
print ("the func run time is %s"%(stop_time - start_time))
return warpper @timmer
def test1():
time.sleep(3)
print ("this is test1") test1()
# this is test1
# the func run time is 3.019197702407837 '''
# 函数即"变量"
# 新概念:函数在内存中以变量形式存放
# 匿名函数没有函数名,当运行后内存会被立马回收(def 定义的函数,不会被内存回收,当程序结束后内存地址才会释放)
'''
# eg_v1
def bar(): # 正常运行
print ("in the bar")
def foo():
print ("in the foo")
bar()
foo()
# in the foo
# in the bar # eg_v2 # 正常运行
def foo():
print ("in the foo")
bar()
def bar():
print ("in the bar")
foo()
# in the foo
# in the bar # eg_v3 # 抛出异常
def foo():
print ("in the foo")
bar()
foo()
def bar():
print ("in the bar")
# Traceback (most recent call last):
# in the foo
# File "E:/pycharm-project/PYTHON自动化课程/第二模块/课堂笔记/装饰器_v1.py", line 92, in <module>
# foo()
# File "E:/pycharm-project/PYTHON自动化课程/第二模块/课堂笔记/装饰器_v1.py", line 91, in foo
# bar()
# NameError: name 'bar' is not defined
'''
# 高阶函数
# eg_v1
'''
def bar():
print ("in the bar") def test1(func):
print (func)
# test1(bar)
# # <function bar at 0x0000024DE92E3E18> bar函数的内存地址
''' # eg_v2
'''
def bar():
print ("in the bar") def test1(func):
print (func)
func() # 2 调用func函数时,也运行了bar函数
test1(bar) # 1 将bar函数传递给test1
# <function bar at 0x00000216F49D3E18>
# in the bar
''' # eg_v3 # 装饰器第一步(没有修改源代码,但改变了调用方式)(test1为装饰函数,bar函数为被装饰函数)
'''
import time
def bar():
time.sleep(2)
print ("in the bar") def test1(func):
start_time = time.time()
func()
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 2.000016689300537
''' # eg_v4 '''
import time
def bar():
time.sleep(2)
print("in the bar") def test2(func):
print (func)
return func
# t = test2(bar) # 将test2(bar) 赋值给t,t() == 调用test2函数,改变了调用方式
# t()
# # <function bar at 0x00000172B2CF3E18>
# # in the bar
bar = test2(bar) # # 将test2(bar) 赋值给bar,bar() == 调用test2函数,未改变了调用方式
bar()
# <function bar at 0x0000016C6E663E18>
# in the bar
'''
# 嵌套函数
# eg_v1
'''
def foo():
print ("in the foo")
def bar():
print ("in the bar") bar()
foo()
''' # eg_v2 # 局部作用域和全局作用域的访问顺序
'''
x = 0
def grandpa():
x = 1
def dad():
x = 2
def son():
x = 3
print (x)
son()
dad()
grandpa()
# 3
'''
# 写一个简单的装饰器
# eg_v1 不使用语法糖
'''
import time def timer(func): # timer(test1) --> func= test1
def deco():
start_time = time.time()
func() # run test1()
stop_time = time.time()
print ("the func run time %s:"%(stop_time - start_time))
return deco def test1():
time.sleep(3)
print ("in the test1") def test2():
time.sleep(3)
print ("in the test2")
test1 = (timer(test1)) # 赋值必须与被装饰的函数同名
test1()
# in the test1
# the func run time 3.0068588256835938:
'''
# eg_v2 使用语法糖,不带参数
'''
import time def timer(func): # timer(test1) --> func= test1
def deco():
start_time = time.time()
func() # run test1()
stop_time = time.time()
print ("the func run time %s:"%(stop_time - start_time))
return deco @timer
def test1():
time.sleep(3)
print ("in the test1")
@timer
def test2():
time.sleep(3)
print ("in the test2") test1()
test2()
# in the test1
# the func run time 3.000098705291748:
# in the test2
# the func run time 3.0001633167266846:
'''
# eg_v2 使用语法糖,被装饰函数带参数
'''
import time def timer(func): # timer(test1) --> func= test1
def deco(*args,**kwargs):
start_time = time.time()
func(*args,**kwargs) # run test1()
stop_time = time.time()
print ("the func run time %s:"%(stop_time - start_time))
return deco @timer
def test1():
time.sleep(3)
print ("in the test1")
@timer
def test2(name): # test2 = timer(test2) == deco test2(name) == deco(name)
time.sleep(3)
print ("in the test2",name) test1()
test2("xieshengsen")
# in the test1
# the func run time 3.0004942417144775:
# in the test2 xieshengsen
# the func run time 3.0003535747528076:
'''
# eg_v3
# 一个简单的登陆页面认证过程(装饰器)(装饰函数带参数)
user = "aaaaaa"
pawd = "123456" 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 username == user and password == pawd:
print ("login....")
res = func(*args,**kwargs) # from home
print ("-*-*-*-*-after auth-*-*-*-*-")
return res
else:
print ("invalid...")
elif auth_type == "ldap":
input("ldap")
print ("use ladp auth...")
return wrapper
return outer_wrapper def index():
print ("welcome to index page.") @auth(auth_type="local")
def home():
print("welcome to home age.") @auth(auth_type="ldap")
def bbs():
print("welcome to bbs age.") index()
home()
bbs()
另 一些关于装饰器介绍的实例
来自:http://blog.csdn.net/yhy1271927580/article/details/72758577
"""
被装饰的对象为函数,且不带参数
简要说明: @timeit装饰器对sleep函数进行了装饰,这是一个装饰器不带参数的装饰器,当sleep函数调用的时候,调用的并不是我们看到的原始的sleep函数,而是装饰过后的sleep函数。这个装饰的过程会发生在调用sleep函数之前发生。
装饰的过程:原生的sleep函数作为参数传递到timeit装饰器函数的fn参数,通过@wraps这个装饰器将fn的属性赋值给底下需要返回的wrap函数,最后返回wrap函数,由此可间,wrap就是装饰过后的sleep函数了。那么在调用新sleep函数的时候,就是调用wrap函数,sleep函数的参数2,被wrap函数的*args、**kwargs这两个可变参数接收。
整个装饰的目的就是将原生的sleep函数,扩充了一个print(nowTime() - start)的过程。
"""
from time import sleep as sleeping
from time import time as nowtime
from functools import wraps def timeit(fn):
@wraps(fn)
def wrap(*args,**kwargs):
start = nowtime()
ret = fn(*args,**kwargs)
print (nowtime() - start)
return ret
return wrap @timeit
def sleep(n):
sleeping(n)
print("sleep time {}s".format(n))
return n sleep(2)
print("%s func" % sleep.__name__)
# sleep time 2s
# 2.0028135776519775
# sleep func
"""
被装饰的对象为函数,且带参数
简要说明: @timeit装饰器对sleep函数进行了装饰,这是一个装饰器是带参数的装饰器.
这个装饰器由于需要传递参数,因此需要两层装饰,第一层是接受传递的参宿,第二层是接收传递进来的需要装饰的函数当sleep函数调用的时候,调用的并不是我们看到的原始的sleep函数,而是装饰过后的sleep函数。
装饰的过程:装饰器第一次接收cpu_time参数,然后返回一个dec装饰器,而这个dec装饰器会被再次调用,传入参数是原生的sleep函数,原生的sleep函数作为参数传递到dec装饰器函数的fn参数,通过@wraps这个装饰器将fn的属性赋值给底下需要返回的wrap函数,最后返回wrap函数
在调用新sleep函数的时候,就是调用wrap函数,sleep函数的参数2,被wrap函数的*args、**kwargs这两个可变参数接收。整个装饰的目的就是将原生的sleep函数,扩充了一个time_func = time.clock if cpu_time else time.time和print(nowTime() - start)的过程
"""
from functools import wraps
import time def timeit(cpu_time=False):
print("timeit") def dec(fn):
@wraps(fn)
def wrap(*args,**kwargs):
start = time.time()
ret = fn (*args,**kwargs)
print(time.time() - start)
return ret
return wrap
return dec @timeit(False)
def sleep(n):
time.sleep(n)
print ("time sleep")
return n sleep(2)
print("%s func" % sleep.__name__)
# timeit
# time sleep
# 2.009625196456909
# sleep func
python装饰器介绍的更多相关文章
- Python 装饰器(无参,有参、多重))
Python装饰器介绍 在Python中,装饰器(decorator)是在闭包的基础上发展起来的. 装饰器的实质是一个高阶函数,其参数是要装饰的函数名,其返回值是完成装饰的函数名,其作用是为已经存在的 ...
- 关于python装饰器
关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...
- Python 装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...
- Python装饰器详解
python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...
- Python装饰器由浅入深
装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...
- Python装饰器与面向切面编程
今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...
- python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释. 今天查看dja ...
- (转载)Python装饰器学习
转载出处:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方 ...
- Python装饰器学习
Python装饰器学习(九步入门) 这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 ? 1 2 3 4 5 6 7 8 # -*- ...
随机推荐
- Wordpress安装Redis为网站加速
前面我们讲了宝塔Linux面板安装Redis,现在我们来举一些例子来看看redis的实际运用,比如Wordpress安装Redis为网站加速,下面就跟着ytkah一起来操作一下. 第一,下载predi ...
- JDBC和hibernate,mybatis的比较
在学习使用mybatis之前,先比较下jdbc编程和hibernate编程各自的优缺点. JDBC: 我们平时使用jdbc进行编程,大致需要下面几个步骤: 1,使用jdbc编程需要连接数据库,注册驱动 ...
- 3 jmeter的两种录制方法
录制1-badboy(推荐) badboy是一款自动化测试工具,它可以完成简单的功能测试和性能测试.其实它是一款独立的测试工具,只不过它录制东西导出的格式适用于jmeter,所以我们经常把jmeter ...
- shell进阶函数
函数的定义和用途 函数function是由若干条shell命令组成的语句块,实现shell代码的重用和模块化编程. 函数和shell程序的异同点 它与shell程序形式上是相似的,不同的是它不是一个单 ...
- HTTP协议(TCP/IP)
HTTP协议(TCP/IP): 服务器套接字(TCP用主机的IP地址加上主机上的端口号作为TCP连接的端点,这种端点就叫做套接字(socket)或插口) 数据包(请求包.报文)http 请求格式: ...
- 以太坊中的账户、交易、Gas和区块Gas Limit等概念
什么是账户 以太坊账户与我们所知的账户概念有一定相似之处,却又有很大的区别,更不同于比特币中UTXO. 账户分两类: - 外部拥有账户(EOA),也就是普通账户 - 合约账户 普通账户 所谓的普通账户 ...
- "pip3 install requests"
后续设置参考 “selenium python3” https://www.cnblogs.com/jpr-ok/p/10108231.html
- [Java in NetBeans] Lesson 00. Getting Set-up for Learning Java
这个课程的参考视频在youtube. 主要学到的知识点有: set up needs Java SE JDK, NetBeans IDE class name should be the same l ...
- MySQL--9存储引擎
存储引擎:存储数据.查询数据的一种技术. 关系型数据库中数据是以表的形式存储的,所以存储引擎也叫表类型.
- .Net拾忆:Asp.net请求管道
w3wp.exe应该很熟悉,调试应用时候附加到进程就是这个服务:w3wp.exe和应用池相关联,每个应用池会有一个w3wp; 一.Http请求到iis应用池 IIS 5.x iis运行在inetinf ...