Discuss / Python / 记录一下我的理解:

记录一下我的理解:

Topic source

綾之桜

#1 Created at ... [Delete] [Delete and Lock User]

首先是练习: 

import functools
import time


# 设计一个decorator, 可作用于任何函数, 并打印该函数执行时间
def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        start = time.time()
        fn(*args, **kw)
        end = time.time()
        print('%s executed in %.4f ms' % (fn.__name__, end - start))
        return fn(*args, **kw)

    return wrapper


@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y


@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z


f = fast(11, 22)
s = slow(11, 22, 33)
# print(f, s)
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')

然后是小结: 

# 设计一个decorator, 能在函数调用的前后打印出'begin call'和'end call'
def log01(text=None):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            if text is not None:
                print('%s begin call %s()' % (text, func.__name__))
                fu = func(*args, **kw)
                print('%s end call %s()' % (text, func.__name__))
            else:
                print('begin call %s()' % func.__name__)
                fu = func(*args, **kw)
                print('end call %s()' % func.__name__)
            return fu

        return wrapper

    return decorator


@log01()  # 这种方法必须加(), 不能直接写@log01
def test1(n):
    print('这里是%sexecuted log测试' % n)


@log01('executed')
def test2(n):
    print('这里是%sexecuted log测试' % n)


# 结果检验
test1('无')
test2('有')

綾之桜

#2 Created at ... [Delete] [Delete and Lock User]

最后参考评论区大佬得出的结果, 感谢! 

# 另一种方法
def log02(text):
    if isinstance(text, str):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print('%s begin call %s()' % (text, func.__name__))
                fu = func(*args, **kw)
                print('%s end call %s()' % (text, func.__name__))
                return fu

            return wrapper

        return decorator

    else:
        @functools.wraps(text)
        def wrapper1(*args, **kw):
            print('begin call %s()' % text.__name__)
            fu = text(*args, **kw)
            print('end call %s()' % text.__name__)
            return fu

        return wrapper1


@log02
def test3(n):
    print('这里是%sexecuted log测试' % n)


@log02('executed')
def test4(n):
    print('这里是%sexecuted log测试' % n)


# 结果检验
test3('无')
test4('有')

请问小姐姐一下,为什么作业里面:因为作业和小结一很类似,小结一里面

def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        start = time.time()
   ////     fn(*args, **kw)////第五句不会导致运行的时候出现两次fn的结果呢,也就是在运行fast函数的时候不出现      “33
                                                                                                                  fast executed in ....ms
                                                                                                                  33”这种情况
        end = time.time()
        print('%s executed in %.4f ms' % (fn.__name__, end - start))
        return fn(*args, **kw)

    return wrapper


因为作业和小结一很类似,小结一里面
if text is not None:
                print('%s begin call %s()' % (text, func.__name__))
              ////  fu = func(*args, **kw)////这一句如果不把函数赋值给一个变量的时候,运型fast函数就会出现“begin call
                                                                                            33
                                                                                           end call
                                                                                             33”这种情况
                print('%s end call %s()' % (text, func.__name__))
            else:
                print('begin call %s()' % func.__name__)
                fu = func(*args, **kw)
                print('end call %s()' % func.__name__)
            return fu

跪求小姐姐解答一下好吗。。。

感觉有缺陷啊

def metric(fn):
    @functools.wraps(fn)
    def wrapper(*args, **kw):
        start = time.time()
        fn(*args, **kw)
        end = time.time()
        print('%s executed in %.4f ms' % (fn.__name__, end - start))
        return fn(*args, **kw)
    return wrapper

@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y

从代码分析  f=fast()实际是metric(fast)==>metric返回wrapper函数,wrapper(x,y),在wrapper执行了fast,然后又返回fast,fast还会执行一次,等于是执行了两次。  可以在fast(x, y):print(“执行我” time.sleep(0.0012)验证     应该是v=fun(xxxx)   return v才对。

从代码分析

同楼上我也发现了这个问题,有什么办法能改进一下不让它执行两次呢?

改成这样:

   
 def wrapper(*args, **kw):
        start = time.time()
        f = fn(*args, **kw)
        end = time.time()
        print('%s executed in %.4f ms' % (fn.__name__, end - start))
        return f

  • 1

Reply