从抽象方法继承包装器
Inherit wrapper from abstract method
我想系统地包装一些基类的重写方法 class。
我正在使用 ABC
作为基础 class。我试着把 @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 方式?
如您所见,装饰器不会更改重写的方法。您可以在每次创建 subclass 时修饰该方法。您甚至可以使用魔术方法 __init_subclass__
.
自动执行此操作
class Base(ABC):
...
def __init_subclass__(cls):
cls.test = print_before(cls.test)
但我不推荐这种方法。它可能会破坏 ABC
机制,并且从 Extend
继承的 classes 如果不覆盖该方法,则会被修饰两次。
这里有一个更简单的方法。我们在 Base
上定义了一个具体的 "public" 方法,它调用了一个抽象的 "private" 方法。在子 classes 中,我们必须实现 "private" 方法。
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()
另一个优点是您可以在子 class 中更改 "wrapper" 的行为,这对于装饰器来说很难。
我想系统地包装一些基类的重写方法 class。
我正在使用 ABC
作为基础 class。我试着把 @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 方式?
如您所见,装饰器不会更改重写的方法。您可以在每次创建 subclass 时修饰该方法。您甚至可以使用魔术方法 __init_subclass__
.
class Base(ABC):
...
def __init_subclass__(cls):
cls.test = print_before(cls.test)
但我不推荐这种方法。它可能会破坏 ABC
机制,并且从 Extend
继承的 classes 如果不覆盖该方法,则会被修饰两次。
这里有一个更简单的方法。我们在 Base
上定义了一个具体的 "public" 方法,它调用了一个抽象的 "private" 方法。在子 classes 中,我们必须实现 "private" 方法。
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()
另一个优点是您可以在子 class 中更改 "wrapper" 的行为,这对于装饰器来说很难。