首页 > 解决方案 > 如何自动将数字特殊方法添加到类中?

问题描述

是否有可能以某种方式拦截Python 中类的数字魔法或 dunder 方法?适用于所有“__getattr__正常”方法,但它不会拦截__add__,__mul__等方法。我认为这可能有一些元类?内置dataclass包似乎有点接近我正在寻找的东西。

例如。我想创建一个类,它将拦截对、等的Number所有方法调用。这似乎不起作用:__add____mul____truediv__

class Number(int):
    def __repr__(self):
        return "I am a number"

a = Number()
b = Number()

c = a + b # this will not preserve the subclass (Number)

我想要什么:

class Number(NumberMetaClass):
    def __repr__(self):
        return "I am a number"

    def intercept_special_numeric(self, special_method, *args):
        print("intercept")
        return special_method(*args)

a = Number()
b = Number()

c = a + b # subclass is preserved and this will print "intercept"

或者也许只是:

class Number(NumberMetaClass):
    def __repr__(self):
        return "I am a number"

    def __getattr_special__(self, dunder_attr):
        print("intercept")
        return getattr(Number, dunder_attr)

标签: pythonpython-3.x

解决方案


所以如果我理解正确,你想从一个类型继承,也想拦截它的方法。我对吗?

您可以对元编程和元类做同样的事情。但我认为使用“类装饰器”要简单得多。这是我的方法:

from functools import wraps


def intercept_numeric_methods(cls):
    def method_decorator(fn):

        @wraps(fn)
        def inner(*args, **kwargs):
            print('Intercepted')
            return fn(*args, **kwargs)

        return inner

    numeric_methods = {'__add__', '__mul__'}

    for method_name, method in int.__dict__.items():
        if method_name in numeric_methods:
            setattr(cls, method_name, method_decorator(method))

    return cls


@intercept_numeric_methods
class Myclass(int):
    pass


obj1 = Myclass(10)
obj2 = Myclass(20)

print(obj1 + obj2)

我刚刚添加了__add____mul__。将您想要的方法的名称添加到numeric_methods集合中。


推荐阅读