
编程开发
切片copy
当我们需要在Go语言中复制一个切片时,我们可以使用内置的copy函数。copy函数可以将一个切片的元素复制到另一个切片中。下面是一个示例: 在上面的示例中,我们首先创建了一个源切片
#!/usr/bin/python3
#coding:utf-8
#~~~~~~~~~~~~www.wulaoer.org 吴老二个人博客~~~~~~~
def one(func):
print("这是第一个函数")
return func
@one
def two():
print("这是第二个函数")
two()
输出结果:这是第一个函数 这是第二个函数这里记住,然后one函数中没有返回值,就会提示“TypeError: 'NoneType' object is not callable”这是因为函数没有return造成的,这就是装饰器的本质,返回函数的函数。因为给two函数加了一个装饰器,这里在调用two函数的时候先调用了one函数,后在调用two函数,这里的顺序要清楚。这里我们可以理解为在调用two函数之前给two函数增加一个函数。
#!/usr/bin/python3
#coding:utf-8
#~~~~~~~~~~~~www.wulaoer.org 吴老二个人博客~~~~~~~
from time import time, sleep
def run_time(func):
def wrapper():
start = time()
func() # 函数在这里运行
end = time()
cost_time = end - start
print("func time run time {}".format(cost_time))
return wrapper
@run_time
def one():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func one run time {}".format(cost_time))
@run_time
def two():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func two run time {}".format(cost_time))
@run_time
def three():
start = time()
sleep(1)
end = time()
cost_time = end - start
print("func three run time {}".format(cost_time))
one()
sleep(1)
two()
sleep(1)
three()
sleep(1)
输出结果:
func one run time 1.0035791397094727 func time run time 1.0036320686340332 func two run time 1.00187087059021 func time run time 1.0019142627716064 func three run time 1.0040409564971924 func time run time 1.004103183746338这里写了三个统计函数运行时间的函数,有使用了一个嵌套函数做装饰器,把内部函数的返回值作为装饰器的返回值,这个用专业的来说是闭包,简单说就是函数内嵌套。然后每个函数上加一个@run_time,相当于家了一个装饰器,这叫通过闭包实现装饰器。
#!/usr/bin/python3
#coding:utf-8
#~~~~~~~~~~~~www.wulaoer.org 吴老二个人博客~~~~~~~
from time import time, sleep
def logger(msg=None):
def run_time(func):
def wrapper(*args, **kwargs):
start = time()
func() # 函数在这里运行
end = time()
cost_time = end - start
print("[{}] func three run time {}".format(msg, cost_time))
return wrapper
return run_time
@logger(msg="One")
def fun_one():
sleep(1)
@logger(msg="Two")
def fun_two():
sleep(1)
@logger(msg="Three")
def fun_three():
sleep(1)
fun_one()
fun_two()
fun_three()
输出结果:
[One] func three run time 1.0034739971160889 [Two] func three run time 1.0036709308624268 [Three] func three run time 1.0021088123321533这是装饰器传参,带参数的装饰器通过前面简单的例子应该已经明白装饰器的价值和它的简单用法:通过闭包来实现装饰器,函数作为外层函数的传入参数,然后在内层函数中运行、附加功能,随后把内层函数作为结果返回。除了上述简单的用法还有一些更高级的用法,比如用装饰器进行类型检查、添加带参数的的装饰器等。它们的用法大同小异,关于高级用法,这里以带参数的装饰器为例进行介绍。不要把问题想的太复杂,带参数的装饰器其实就是在上述基本的装饰器的基础上在外面套一层接收参数的函数,下面通过一个例子说明一下。
#!/usr/bin/python3 #coding:utf-8 #~~~~~~~~~~~~www.wulaoer.org 吴老二个人博客~~~~~~~ import logging from functools import partial def wrapper_property(obj, func=None): if func is None: return partial(wrapper_property, obj) setattr(obj, func.__name__, func) return func def logger_info(level, name=None, message=None): def decorate(func): logmsg = message if message else func.__name__ def wrapper(*args, **kwargs): logging.log(level, logmsg) return func(*args, **kwargs) @wrapper_property(wrapper) def set_level(newlevel): nonlocal level level = newlevel @wrapper_property(wrapper) def set_message(newmsg): nonlocal logmsg logmsg = newmsg return wrapper return decorate @logger_info(logging.WARNING) def main(x, y): return x + y main(3,3) main.set_level(logging.ERROR) main(5, 5)输出结果:
WARNING:root:main ERROR:root:main我们还可以对装饰器添加一些属性,就如同给一个类定义实现不同功能的方法那样。以输出日志为例,初学Python的同学都习惯用print打印输出信息,其实这不是一个好习惯,当开发商业工程时,你很用意把一些信息暴露给用户。在开发过程中,我更加鼓励使用日志进行输出,通过定义WARNING、DEBUG、INFO等不同等级来控制信息的输出,比如INFO是可以给用户看到的,让用户直到当前程序跑到哪一个阶段了。DEBUG是用于开发人员调试和定位问题时使用。WARING是用于告警和提示。那么问题来了,如果我们预先定义一个打印日志的装饰器
评论 0