如何使用父类decorator实现依赖实例的功能



我想在我的子类中实现一个父类装饰器,其功能取决于子类实例的状态。我试着从三个不同的角度来解决这个问题,但都没有奏效:


方法

如果give_feedback是一个静态方法,则该方法中没有self。但是,如果它是一个实例方法,那么在应用它的命名空间中就没有self

class Interface:
def __init__(self, quiet=False):
self.quiet = quiet
def echo(self, text):
if not self.quiet:
print(text)
def give_feedback(self, func):
def wrapper(*args):
print('Calling give_feedback.')
self.echo(func(*args))
return wrapper
class App(Interface):
@Interface.give_feedback  # self not defined here.
def app_func(self, num):
feedback = 'Success with {num}'.format(num=num)
return feedback
if __name__ == '__main__':
a = App()
a.app_func(3)

使用__call__的父(参见链接example_1(

无法从__call__中访问对象。

class Interface:
# ...
class give_feedback:
def __init__(self, func):
self.func = func
def __call__(self, *args):
print(
'Calling {func}'.format(func=self.func)
)
instance = get_obj_instance(self.func)  # What is this?
return instance.echo(self.func(instance, *args))
class App(Interface):
# ...
if __name__ == '__main__':
# ...

描述符(参见链接示例_2(

可以访问对象,但没有参数。

class Interface:
# ...
class give_feedback:
# ...
def __get__(self, instance, owner):
print(
'Getting {func} from {inst} of {ownr}'.format(
func=self.func, inst=instance, ownr=owner
)
)
num = 2  # How to get num???
return instance.echo(self.func(instance, num))
class App(Interface):
# ...
if __name__ == '__main__':
a = App()
a.app_func  # No ability to pass parameters.

有好的方法吗?

为什么不组合第二种和第三种方法?使用__get__获取类实例,使用__call__echo进行装饰。与其返回app_func,不如返回一个新对象,该对象包含实例并具有所需的__call__行为。

class Interface:
def __init__(self, quiet=False):
self.quiet = quiet
def echo(self, text):
if not self.quiet:
print(text)
class give_feedback:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return self.InstHolder(instance, self.func)
class InstHolder:
def __init__(self, inst, func):
self.inst = inst
self.func = func
def __call__(self, *args):
return self.inst.echo(self.func(self.inst, *args))

class App(Interface):
@Interface.give_feedback
def app_func(self, num):
feedback = 'Success with {num}'.format(num=num)
return feedback

if __name__ == '__main__':
a = App()
a.app_func(3)
a.quiet = True
a.app_func(4)

相关内容

最新更新