【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
原文地址:https://www.cnblogs.com/xkxf/p/6581259.html