簡體   English   中英

從抽象方法繼承包裝器

[英]Inherit wrapper from abstract method

我想系統地包裝一些基類的重寫方法。

我使用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__自動執行此__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()

另一個優點是您可以更改子類中“包裝器”的行為,這對於裝飾器來說是困難的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM