code:
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 30 19:51:10 2019
@author: buu
"""
'''
通过下面的代码可以看出:
1. 有@functool.wraps()时,函数testfunc1()是它自己,即;
2. 没有@functools.wraps(),函数testfunc1()指向了wrapper_func(),即.wrapper_func at 0x00000000086A0488>;
3. 对于闭包函数的属性的查看:
不管有没有@functool.wraps(),函数testfun()仍拥有wrapper_func.time这个属性,并且testfunc1可以修改,
但对这个属性的修改仅限于testfunc1()本身,并不改变wrapper_func.time的值;
'''
import functools
def wrap(func):
@functools.wraps(func)
def wrapper_func():
print('inside:')
wrapper_func.time+=3
func()
wrapper_func.time=1
return wrapper_func
@wrap
def testfunc1():
print('test 1')
@wrap
def testfunc2():
print('test 2')
if __name__ == '__main__':
testfunc1()
# print('without functools:',testfun)
#without functools: .wrapper_greet at 0x00000000070D9598>
print('with functools:',testfunc1)
#have functools:
# print(wrapper_greet.time)
# 尝试直接输出wrapper_greet.time: NameError: name 'wrapper_greet' is not defined
print('-'*40)
print('首先查看testfunc1是否包含time属性:',dir(testfunc1)) # 包含
print('-'*40)
print('初始时wrapper_func.time:',wrap(testfunc2).time)
# wrap()总得需要一个参数,此处若用testfunc1的话,输出的还是testfunc1的time属性;
print('testfunc1.time=',testfunc1.time)#
testfunc1.time=2
print('testfun1对time进行修改,修改testfunc1.time=',testfunc1.time) #
print('看看wrapper_greet.time是否被修改:',wrap(testfunc2).time) #
print()
testfunc2()
testfunc2.age=10
print('testfun2未被装饰时包含的属性:包含age')
print('testfun2被装饰后包含的属性:包含age和time')
practice:
bubble_sort.py
Python代码a, b = b, a称为一次swap .
函数bubble_sort(L, func=operator.lt), 功能为对整数list L进行in-place 冒泡排序, 返回 swap count, 比较规则为func, func缺省为小于(operator.lt, 即<) 最后返回交换次数;
dec_func.py
写一个 function decorator 来装饰 bubble_sort() 函数, 该函数请从bubble_sort.py 中直接 import, 装饰器的功能是报告每一次bubble sort完成排序工作所花去的时间(以秒计), 并最终统计调用次数和总时间花销(即累加各次的时间花销).
一次输出为:
dec_nested.py
写两个 decorators 来嵌套装饰 bubble_sort() 函数, 第一个装饰器函数 timer() 从第40题的dec_func.py中直接import.
一次输出为:
code1: bubble_sort.py
def bubble_sort(L,func=operator.lt): # func:<
'''
将L从小到大排序;
'''
swap_count=0
length=len(L)
l=len(L)
for i in range(length): # 用来控制一趟冒泡排序;
for j in range(l-1):# j取值:0-->length-2 ,用来控制每趟排序的交换次数;
if not func(L[j],L[j+1]):
L[j],L[j+1]=L[j+1],L[j]
swap_count+=1
l-=1 # 一趟结束后,最大的沉底,所以最大的不必再参与排序;
return swap_count
code2: dec_func.py
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 22 09:13:02 2019
@author: buu
"""
import numpy as np
import operator,functools,time
from bubble_sort import bubble_sort
def timer(func):
@functools.wraps(func)
def wrapper_timer(ls,g):
wrapper_timer.ncalls+=1
print("排序前序列的前5个数为:",end='')
for i in range(5):
print(ls[i],end=' ')
print()
t0=time.time()
swapcnt= func(ls,g)
t=time.time()-t0
print("排序后序列的前5个数为:",end='')
for i in range(5):
print(ls[i],end=' ')
print()
print(f"bubble_sort花了{t:.4f}秒,swapcount = {swapcnt}")
wrapper_timer.time+=t
return swapcnt
wrapper_timer.time=0
wrapper_timer.ncalls=0
return wrapper_timer
if __name__ == '__main__':
bubble_sort = timer(bubble_sort)
for i in range(np.random.randint(3,8)):
n=np.random.randint(1000, 3001)
L=list(np.random.permutation(n))
func = operator.gt
swapcnt = bubble_sort(L, func)
print(f'\n共调用{bubble_sort.__name__}函数{bubble_sort.ncalls}次, 总时间为{bubble_sort.time:.2f}秒.',end='')
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 22 16:12:12 2019
@author: buu
"""
import numpy as np
import operator, functools, time, sys
from bubble_sort import bubble_sort
from dec_func import timer
def star(c1='-', c2='*', repeat=42):
def wrapper_star(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
wrapper.ncalls+=1
print(f"第{wrapper.ncalls}次调用{func.__name__}:")
print(c1*repeat)
t0=time.time()
ret=func(*args,**kwargs)
t=time.time()-t0
wrapper.time+=t
print(c2*repeat)
print()
return ret
wrapper.ncalls=0
wrapper.time=0
return wrapper
return wrapper_star
if len(sys.argv) == 1:
bubble_sort = star()(timer(bubble_sort))
else:
bubble_sort = star(c1=sys.argv[1],c2=sys.argv[2],repeat=int(sys.argv[3]))(timer(bubble_sort))
for i in range(np.random.randint(3, 8)):
n = np.random.randint(1000, 3001)
L = list(np.random.permutation(n))
func = operator.gt
cnt=bubble_sort(L,func)
print(f'\n共调用{bubble_sort.__name__}函数\
{bubble_sort.ncalls}次, 总时间为{bubble_sort.time:.2f}秒.')
code3输出:部分结果
下面说一下为什么在code3中,装饰器star()内要再次定义time,ncalls变量:
因为star()有缺省参数,因此需要写成3个函数嵌套;
2个嵌套就能直接获取func.ncalls or func.time,但是3层嵌套就不行了.
end