如何装饰子类中的所有继承方法 [英] How can I decorate all inherited methods in a subclass

查看:38
本文介绍了如何装饰子类中的所有继承方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class Reader:
    def __init__(self):
        pass

    def fetch_page(self):
        with open('/dev/blockingdevice/mypage.txt') as f:
            return f.read()

    def fetch_another_page(self):
        with open('/dev/blockingdevice/another_mypage.txt') as f:
            return f.read()   

class Wrapper(Reader):
    def __init__(self):
        super().__init__()

    def sanity_check(func):
        def wrapper():
            txt = func()
            if 'banned_word' in txt:
                raise Exception('Device has banned word on it!')
        return wrapper

    @sanity_check
    <how to automatically put this decorator on each function of base class? >

w = Wrapper()
w.fetch_page()
w.fetch_another_page()

在调用 fetch_page fetch_another_page 时,如何确保自动运行 sanity_check wrapper Wrapper 类的实例?

How can I make sure that sanity_check's wrapper was run automatically when calling fetch_page and fetch_another_page on an instance of the Wrapper class?

推荐答案

如果使用python3.6或更高版本,则可以使用

If using python3.6 or above, you can accomplish this using __init_subclass__

简单的实现:(实际上,您可能想要一个注册表和 functools.wraps 等):

Simple implementation: (for the real thing you probably want a registry and functools.wraps, etc):

class Reader:
    def __init_subclass__(cls):
        cls.fetch_page = cls.sanity_check(cls.fetch_page)
        cls.fetch_another_page = cls.sanity_check(cls.fetch_another_page)

    def fetch_page(self):
        return 'banned_word'

    def fetch_another_page(self):
        return 'not a banned word'

class Wrapper(Reader):
    def sanity_check(func):
        def wrapper(*args, **kw):
            txt = func(*args, **kw)
            if 'banned_word' in txt:
                raise Exception('Device has banned word on it!')
            return txt
        return wrapper


演示:

In [55]: w = Wrapper()

In [56]: w.fetch_another_page()
Out[56]: 'not a banned word'

In [57]: w.fetch_page()
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-57-4bb80bcb068e> in <module>()
----> 1 w.fetch_page()
...

Exception: Device has banned word on it!

如果您不能更改基类,则可以子类化并创建一个Adapter类:

In case you can't change the baseclass, you can subclass and create an Adapter class:

class Reader:

    def fetch_page(self):
        return 'banned_word'

    def fetch_another_page(self):
        return 'not a banned word'

class ReadAdapter(Reader):
    def __init_subclass__(cls):
        cls.fetch_page = cls.sanity_check(cls.fetch_page)
        cls.fetch_another_page = cls.sanity_check(cls.fetch_another_page)

class Wrapper(ReadAdapter):
    def sanity_check(func):
        def wrapper(*args, **kw):
            txt = func(*args, **kw)
            if 'banned_word' in txt:
                raise Exception('Device has banned word on it!')
            return txt
        return wrapper

应提供相同的结果.

这篇关于如何装饰子类中的所有继承方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆