首页 > 解决方案 > 有没有办法知道一个方法是否是一个运算符?

问题描述

我有一个方法名称列表:

['__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)

标签: pythonpython-3.8

解决方案


好吧,我找到了方法!只是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)

推荐阅读