有没有办法知道一个方法是否是一个操作符?

Is there a way to know whether a method is an operator?

我有一个方法名称列表:

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

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


我的 class 是用这些运算符进行猴子修补的,我想要一种方法让猴子修补程序知道该方法是否是一个运算符,而不必告诉它。

这将使使用 'reverse operator'(例如: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)

好的,我找到了怎么做!只是 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)