有没有办法知道一个方法是否是一个运算符?

时间:2020-10-14 15:41:03

标签: python python-3.8

我有一个方法名列表:

['__add__', 'upper', '__mul__']

是否有办法知道它们是否是运算符方法?请注意,检测dunders是不够的,因为并非所有dunder方法都是运算符


我的班级是用那些运算符修补的,我想让猴子修补程序知道该方法是否是运算符的一种方法,而不必这么讲。

这将使得在普通other.__radd__(self)时使用“反向运算符”(例如:NotImplemented)更容易。

def make_wrappers(cls, operators =[], methods=[]):
    """Make wrapper methods for the given class

    This rewires self.method to self.value.method
    
    operators will also try the reverse operator
    ex : __add__ will try __radd__ if __add__ returns NotImplemented
    """

    for method in operators:
        def wrapper(self, other, *args, _method=method, **kwargs):
            """Tries operator on self.value, then reverse operator if NotImplemented"""
            result = getattr(self.value, _method)(other, *args, **kwargs)

            if result is NotImplemented:
                _method = f'__r{_method.strip("_")}__'
                result = getattr(other, _method)(self.value, *args, **kwargs)

            return type(self)(result)

        setattr(cls, method, wrapper)
    
    for method in coercedMethods:
        def wrapper(self, *args, _method=method, **kwargs):
            return type(self)( getattr(self.value, _method)(*args, **kwargs) )
        setattr(cls, method, wrapper)
    
    # This makes sure ABC doesn't refuse instanciation
    cls.__abstractmethods__ = cls.__abstractmethods__.difference(operators, methods)

1 个答案:

答案 0 :(得分:2)

好的,我找到了怎么做!只需import operator并选中if method in dir(operator)

import operator

def make_wrappers(cls, methods=[]):
    """Make wrapper methods for the given class

    This rewires self.method to self.value.method
    
    operators will also try the reverse operator
    ex : __add__ will try __radd__ if __add__ returns NotImplemented
    """
    for method in methods:
        if method in dir(operator):
            def wrapper(self, *args, _method=method, **kwargs):
                return getattr(operator, _method)(self.value, *args, **kwargs)
            setattr(cls, method, wrapper)
        else:
            def wrapper(self, *args, _method=method, **kwargs):
                return getattr(self.value, _method)(*args, **kwargs)
            setattr(cls, method, wrapper)
    
    # This makes sure ABC doesn't refuse instanciation
    cls.__abstractmethods__ = cls.__abstractmethods__.difference(coercedMethods, nonCoercedMethods)