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
  • 相关阅读:
    PAT顶级 1024 Currency Exchange Centers (35分)(最小生成树)
    Codeforces 1282B2 K for the Price of One (Hard Version)
    1023 Have Fun with Numbers (20)
    1005 Spell It Right (20)
    1092 To Buy or Not to Buy (20)
    1118 Birds in Forest (25)
    1130 Infix Expression (25)
    1085 Perfect Sequence (25)
    1109 Group Photo (25)
    1073 Scientific Notation (20)
  • 原文地址:https://www.cnblogs.com/xkxf/p/6581259.html
Copyright © 2011-2022 走看看