我如何在Python中制作两个装饰器来完成以下操作?

@make_bold
@make_italic
def say():
   return "Hello"

调用say()应返回:

"<b><i>Hello</i></b>"

当前回答

Python装饰器为另一个函数添加了额外的功能

斜体装饰符可以如下所示

def makeitalic(fn):
    def newFunc():
        return "<i>" + fn() + "</i>"
    return newFunc

注意,函数是在函数内部定义的。它基本上是用新定义的函数替换函数。例如,我有这门课

class foo:
    def bar(self):
        print "hi"
    def foobar(self):
        print "hi again"

现在,我希望两个函数在完成后和完成前都打印“---”。我可以在每个打印语句前后添加一个打印“---”。但因为我不喜欢重复自己,我会做一个装饰师

def addDashes(fn): # notice it takes a function as an argument
    def newFunction(self): # define a new function
        print "---"
        fn(self) # call the original function
        print "---"
    return newFunction
    # Return the newly defined function - it will "replace" the original

所以现在我可以把我的班级改成

class foo:
    @addDashes
    def bar(self):
        print "hi"

    @addDashes
    def foobar(self):
        print "hi again"

有关装饰器的详细信息,请查看http://www.ibm.com/developerworks/linux/library/l-cpdecor.html

其他回答

装饰器接受函数定义并创建一个新函数,该函数执行该函数并转换结果。

@deco
def do():
    ...

相当于:

do = deco(do)

例子:

def deco(func):
    def inner(letter):
        return func(letter).upper()  #upper
    return inner

This

@deco
def do(number):
    return chr(number)  # number to letter

相当于这个

def do2(number):
    return chr(number)

do2 = deco(do2)

65<=>“a”

print(do(65))
print(do2(65))
>>> B
>>> B

要理解decorator,需要注意的是,decorator创建了一个新的函数do,它在内部执行函数并转换结果。

下面有make_bold()和make_italic():

def make_bold(func):
    def core(*args, **kwargs):
        result = func(*args, **kwargs)
        return "<b>" + result + "</b>"
    return core

def make_italic(func):
    def core(*args, **kwargs):
        result = func(*args, **kwargs)
        return "<i>" + result + "</i>"
    return core

您可以使用say()将它们用作装饰器,如下所示:

@make_bold
@make_italic
def say():
   return "Hello"

print(say())

输出:

<b><i>Hello</i></b>

当然,您可以直接使用make_bold()和make_italic()而不使用修饰符,如下所示:

def say():
    return "Hello"
    
f1 = make_italic(say)
f2 = make_bold(f1)
result = f2()
print(result)

简而言之:

def say():
    return "Hello"
    
result = make_bold(make_italic(say))()
print(result)

输出:

<b><i>Hello</i></b>

装饰只是语法上的糖。

This

@decorator
def func():
    ...

扩展到

def func():
    ...
func = decorator(func)

说到计数器示例-如上所述,计数器将在使用decorator的所有函数之间共享:

def counter(func):
    def wrapped(*args, **kws):
        print 'Called #%i' % wrapped.count
        wrapped.count += 1
        return func(*args, **kws)
    wrapped.count = 0
    return wrapped

这样,您的装饰器可以重复用于不同的函数(或用于多次装饰同一个函数:func_counter1=counter(func);func_counter2=counter(func)),并且计数器变量将对每个变量保持私有。

用于绘制图像的嵌套装饰器的又一示例:

import matplotlib.pylab as plt

def remove_axis(func):
    def inner(img, alpha):
        plt.axis('off')
        func(img, alpha)
    return inner

def plot_gray(func):
    def inner(img, alpha):
        plt.gray()
        func(img, alpha)
    return inner

@remove_axis
@plot_gray
def plot_image(img, alpha):
    plt.imshow(img, alpha=alpha)
    plt.show()

现在,让我们先使用嵌套的装饰器显示一个没有轴标签的彩色图像:

plot_image(plt.imread('lena_color.jpg'), 0.4)

接下来,让我们使用嵌套的装饰器remove_axis和plot_gray显示一个没有轴标签的灰度图像(我们需要cmap='gray',否则默认的颜色映射是viridis,因此除非明确指定,否则默认情况下灰度图像不会以黑白色显示)

plot_image(plt.imread('lena_bw.jpg'), 0.8)

上述函数调用缩减为以下嵌套调用

remove_axis(plot_gray(plot_image))(img, alpha)