装修房屋

2024-09-30 16:40:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图装饰一个实例方法,它用另一个方法打印全名,这个方法只是添加了一个名称,我已经设法弄明白了这一点

class DecoratorTest:

    def __init__(self):
        self._first_name = ['CHARLES', 'WILIAM', 'ENID']
        self._last_name = ['DICKENS', 'SHAKESPEARE', 'BLYTON']
        self._full_name = None

    class designation(object):
        def __init__(self, decorated):
            self._decorated = decorated

        def __call__(self, *args, **kwargs):
            self._full_name = "MR" + self._decorated()
            return self._full_name

    @designation()
    def full_name(self):
        if not self._full_name:
            self._full_name = random.choices(self._first_name) + random.choices(self._last_name)
        return self._full_name

a = DecoratorTest()
print(a.full_name())

通过阅读,我发现decorator@designation不能是一个实例方法,因为第一个参数是self,而不是需要修饰的函数,所以对它的任何调用都会立即失败,这就是为什么我将decoratordesignation指定为一个类,希望重新定义的描述符__call__()在这里会有帮助的

我不知道该怎么做。 我不断地遇到各种各样的错误,没有多少尝试和错误能让我找到解决方案

编辑

经过一段时间的工作,我成功地实现了这一点,尽管是在抛弃了类装饰器之后,但现在的问题是,它是一个实例方法,它提出了我在评论中提到的博客链接中指出的问题,即在这个链接中https://medium.com/@vadimpushtaev/decorator-inside-python-class-1e74d23107f6

我怎样才能解决这个问题

import random

class DecoratorTest:

    def __init__(self):
        self._first_name = ['CHARLES', 'WILIAM', 'ENID']
        self._last_name = ['DICKENS', 'SHAKESPEARE', 'BLYTON']
        self._full_name = None

    def designation(func):
        def wrapper(self):
            full_name = "MR" + func(self)
            return full_name
        return wrapper

    @designation
    def full_name(self):
        if not self._full_name:
            self._full_name = str(random.choices(self._first_name)) + str(random.choices(self._last_name))
        return self._full_name

a = DecoratorTest()
print(a.full_name())

Tags: 实例方法nameselfreturndefrandomfull
2条回答

TLDR(转至底部)

首先让我们提醒自己装饰师是做什么的

它们是可调用函数/函数,将函数作为输入并返回新函数(修饰)

这意味着我们可以装饰这样的功能

def return_hello():
    return "hello "

def multiply_by_5(func):
    def new_func(*args,**kwargs):
        return func(*args, **kwargs) * 5

 multiply_by_5(return_hello)()

或者使用@语法

@multiply_by_5
def return_hello():
    return "hello "

return_hello()

因此,在您的示例中,您已经用

@designation()

这是通过_call _方法模拟可调用的(请参见docs)。这意味着_调用_方法被传递给函数(即_调用_方法实际上是这里的装饰器)

因此,您可以像这样修复代码:

...
class designation():

    def __call__(self, func):
        def new_func(*n_args, **n_kwargs):
            return "MR" + func(*n_args,**n_kwargs)
        return new_func

@designation()
def full_name(self):
    ...

编辑2:你也可以像这样添加属性装饰器,它会工作的

@property
@designation()
def full_name(self):
    ...

编辑3:您也可以通过一个简单的基于函数的装饰器来实现所有这些。所以,除非你真的需要你的装饰者成为一个类,否则我会推荐这个

def designation(func):
    def new_func(*args, **kwargs):
        name = func(*args, **kwargs)
        return "MR" + name
    return new_func

我玩了一会儿,发现了这个解决方案:

class DecoratorTest:

    def __init__(self):
        self._first_name = ['CHARLES', 'WILIAM', 'ENID']
        self._last_name = ['DICKENS', 'SHAKESPEARE', 'BLYTON']
        self._full_name = None

    class designation(object):
        def __init__(self, decorated, *args, **kwargs):
            print(str(*args))
            print(str(**kwargs))
            self._decorated = decorated

        def __call__(self, *args, **kwargs):
            full_name = "MR" + self._decorated(self)
            return full_name

    @designation
    def full_name(self):
        if not DecoratorTest()._full_name:
            full_name = ' '.join([random.choices(DecoratorTest()._first_name)[0], random.choices(DecoratorTest()._last_name)[0]])
        return full_name

主要问题是,您使用内部装饰器类装饰外部方法,这导致了问题,外部方法中的self可能指向内部方法。我使用类名本身来指向正确的值

这只是一个快速的,它可能不是100%准确

你好,托马斯

相关问题 更多 >