具有默认返回值的实例方法的包装器

问题描述 投票:0回答:1

我有十几个(实例)方法,它们应该仅在满足条件时才进行评估,否则返回默认值,每个方法都不同:

def fun(self, *args, **kwargs):
    if not self.init():
        return ... # <- default value, different for each method
    # method logic
    return ... # some value

我设法使用装饰器完成这项工作,如下:

from functools import partial, wraps


def check_init(caller = None, *, ret = None):
    if caller is None:
        return partial(check_init, ret = ret)
    
    @wraps(caller)
    def _check_init(self, *args, **kwargs):
        return caller(self, *args, **kwargs) if self.init() else ret
    return _check_init


class Test:
    num: int = 2

    def init(self) -> bool:
        return self.num < 5

    @check_num(ret = 'Cannot show number')
    def show(self) -> str:
        return 'Number is %d' % self.num


x = Test()

print(x.show()) # "Number is 2"

x.num = 4
print(x.show()) # "Number is 4"

x.num = 6
print(x.show()) # "Cannot show number"

两个问题:

  • 由于所描述的逻辑仅与

    Test
    实例方法相关,因此如何将整个
    def check_init()
    块放入
    Test
    类中?当在课堂外时,我无法用
    self
    Test
    键入提示
    Self

  • 有没有更好(更Pythonic)的方法来实现我想要做的事情?最好使用方法装饰器..

python decorator return-value wrapper default
1个回答
0
投票
  1. 您不需要在类中定义装饰器(我也不推荐它),而是可以通过使用前向引用来键入
    self
    。前向引用是所需类型名称的字符串,可以在定义类型本身之前使用。
def check_init(caller=None, *, ret=None):
    if caller is None:
        return partial(check_init, ret=ret)

    @wraps(caller)
    def _check_init(self: "Test", *args, **kwargs):
        return caller(self, *args, **kwargs) if self.init() else ret
    return _check_init


class Test:
    # ...
  1. 有更好的方法吗?我想不到。如果您需要在各种类类型中使用这些装饰器,那么创建一个定义您的检查 (
    self.init()
    ) 接口的混合类可能是明智之举。
© www.soinside.com 2019 - 2024. All rights reserved.