python - 从抽象方法继承包装器
问题描述
我想系统地包装一些基类的重写方法。
我正在使用ABC
基类。我试图包装@abstractmethod
,将注释放在之前或之后,但它不起作用。据我了解,整个包装的方法被覆盖。
from functools import wraps
from abc import ABC, abstractmethod
def print_before(func):
@wraps(func)
def out(*args, **kwargs):
print('Hello')
return func(*args, **kwargs)
return out
class Base(ABC):
@print_before
@abstractmethod
def test(self):
pass
class Extend(Base):
def test(self):
print('World')
以下是我们测试时发生的情况:
Extend().test()
结果:
World
期望:
Hello
World
我想我没有使用正确的方法来获得这种行为。在覆盖方法之前和之后运行一些代码的一种不错的 Pythonic 方式是什么?
解决方案
正如您所注意到的,装饰器不会更改被覆盖的方法。您可以在每次创建子类时装饰该方法。您甚至可以使用魔术方法自动完成__init_subclass__
。
class Base(ABC):
...
def __init_subclass__(cls):
cls.test = print_before(cls.test)
但我不推荐这种方法。如果它们不重写方法,它可能会破坏ABC
机制和继承的类被装饰两次。Extend
这是一个更简单的方法。我们定义了一个具体的“公共”方法,Base
它调用了一个抽象的“私有”方法。在子类中,我们必须实现“私有”方法。
class Base(ABC):
def test(self):
# do something before
result = self._do_work()
# do something after
return result
@abstractmethod
def _do_work(self):
pass
class Extend(Base):
def _do_work(self):
# your implementation here
# use it like this:
e = Extend()
e.test()
另一个优点是您可以更改子类中“包装器”的行为,这对于装饰器来说是很困难的。
推荐阅读
- php - Symfony 5:错误 - 找不到“GET /
" - html - HTML图片元素在手机上下载错误的图片
- r - 以编程方式更改 data.table 列中的值
- javascript - 关于如何在 render() 中引用状态变量的快速问题 - React Native
- javascript - JavaScript console.log 将对象显示为数组?
- python - Python pyautogui/pynput 点击函数
- python - 如何使用动态 URL 访问数据库项目
- next.js - net::ERR_ABORTED 404 NextJs 生产时
- typescript - 如何从打字稿中的对象键创建对象类型?
- react-native - React Native - 更新由管理的视图的属性“nativeBackgroundAndroid”时出错:RCTView