zoukankan      html  css  js  c++  java
  • 【Python】装饰器 & 偏函数

    【装饰器】

    1、最简单的Decorator。

    def author(f):
        def addName():
            print('My name is xkfx.
    ')
            f()
        return addName
    
    @author
    def helloWorld():
        print('Hello, World')

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

    >>> helloWorld()
    My name is xkfx.
    
    Hello, World

    这个时候查看函数的名字会发现

    >>> helloWorld.__name__
    'addName'

    2、稍微修改一下

    def author(f):
        def addName():
            print('My name is xkfx.[edition-2]
    ')
            return f()
        return addName
    @author
    def helloWorld():
        print('Hello, World')
    >>> helloWorld()
    My name is xkfx.[edition-2]
    
    Hello, World

    将直接调用f();改为return f();执行效果是一样的,先打印author name然后执行原函数。

    3、这个时候希望由用户输入author名,也就是包装器要接收一个字符串参数,那该怎么办?这就需要一个嵌套的decorator:

    def author(authorName): 
        def decorator(func):
            def wrapper(*args, **kw): # wrapper是包装纸的意思
                print("author:" + authorName)
                return func() # 调用原函数,注意是有括号的
            return wrapper # 返回包装后的函数
        return decorator # 返回真正的包装器
    >>> from test import author
    >>> @author('xkfx')
    ... def printHello():
    ...     print('Hello
    ')
    ...
    >>> printHello()
    author:xkfx
    Hello

     查看被包装后的函数名:

    >>> printHello.__name__
    'wrapper'

    需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。而做这件事情本身也属于“拓展函数功能”的范畴,用Python库内置的装饰器完成就可以了。只需记住在定义wrapper()的前面加上@functools.wraps(func)即可,如下所示:

    import functools
    
    def author(authorName): 
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw): # wrapper是包装纸的意思
                print("author:" + authorName)
                return func() # 调用原函数,注意是有括号的
            return wrapper # 返回包装后的函数
        return decorator # 返回真正的包装器
    
    
        

    再走一遍流程:

    >>> printHello.__name__
    'printHello'

     

    4、练习。

    import functools
    
    def log(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('begin call')
            result = func(*args, **kw)
            print('after call')
            return result
        return wrapper
    
    @log
    def f():
        pass

    需求二不会做。

     

    【偏函数】

    当函数的参数太多的时候,可以选择将部分参数固定来简化函数,固定的方式就是使用functools模块中的partial函数

    一个简单的例子,固定谈话对象:

    def say(words, name):
        print(words + ',' + name)

    原函数需要两个参数:

    >>> say('hello', 'xkfx')
    hello,xkfx

    经简化后得到的“偏”函数只需要传入一个参数就够了:

    >>> say2 = functools.partial(say, name='xkfx')
    >>> say2('hi')
    hi,xkfx

     当然固定多个参数肯定是可行的,(实际上是将要固定关键字参数传入了一个隐式的dict)

    >>> say2 = functools.partial(say, name='xkfx', age=19)
    >>> say2('hi')
    hi,xkfx
    Your age is 19
  • 相关阅读:
    利用Dom4j创建xml文档
    eclipse安装、使用hibernate插件方法
    “万能数据库查询分析器”用户已基本涵盖当前所有DBMS
    在Dom4j中使用Xpath搜索xml的元素节点
    多线程的一些小问题集锦
    Dalvik虚拟机的运行过程分析
    创建线程的两种方式
    通过xpath查找指定的节点
    Oracle TNS 配置
    c++五种内存分配、堆与栈区别
  • 原文地址:https://www.cnblogs.com/xkxf/p/6581259.html
Copyright © 2011-2022 走看看