zoukankan      html  css  js  c++  java
  • [Python]返回函数,装饰器拾遗

    def lazy_print(*args):
         def pr():
             print(args)
         return pr

    当我们调用lazy_print()时,返回的并不是求和结果,而是求和函数:

    >>> p = lazy_print(1,2,3,4,5)
    >>> p
    <function lazy_print.<locals>.pr at 0x000000000364ED90>

    调用函数p时,才真正计算求和的结果:

    >>> p()
    (1, 2, 3, 4, 5)

    .....

    一个函数可以返回一个计算结果,也可以返回一个函数。

    返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。

    装饰器

    首先定义一个装饰器:

    def log(fun):    
        def wrapper():
            print('This is wrapper!')
            return fun()
        return wrapper

    观察上面的log,因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

    @log
    def now():
        print('This is now!')

    调用now()函数,不仅会运行now()函数本身,还会在运行now()函数前打印一行日志:

    >>> now()
    This is wrapper!
    This is now!

    @log放到now()函数的定义处,相当于执行了语句:

    now = log(now)

    由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。

    因为我们讲了函数也是对象,它有__name__等属性,但你去看经过decorator装饰之后的函数,它们的__name__已经从原来的'now'变成了'wrapper'

    >>> now.__name__
    'wrapper'

    因为返回的那个wrapper()函数名字就是'wrapper',所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

    不需要编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下

    import functools
    
    def log(fun):
        @functools.wraps(fun)
        def wrapper():
            print('This is wrapper!')
            return fun()
        return wrapper

    import functools是导入functools模块。模块的概念稍候讲解。现在,只需记住在定义wrapper()的前面加上@functools.wraps(func)即可。

    >>> now.__name__
    'now'
  • 相关阅读:
    使用 asp.net mvc和 jQuery UI 控件包
    ServiceStack.Redis 使用教程
    HTC T8878刷机手册
    Entity Framework CodeFirst 文章汇集
    2011年Mono发展历程
    日志管理实用程序LogExpert
    使用 NuGet 管理项目库
    WCF 4.0路由服务Routing Service
    精进不休 .NET 4.0 (1) asp.net 4.0 新特性之web.config的改进, ViewStateMode, ClientIDMode, EnablePersistedSelection, 控件的其它一些改进
    精进不休 .NET 4.0 (7) ADO.NET Entity Framework 4.0 新特性
  • 原文地址:https://www.cnblogs.com/dylan-wu/p/6705149.html
Copyright © 2011-2022 走看看