详解 Python 的二元算术运算,为什么说减法只是语法糖?( 四 )


由于闭包和 Python 在对象自省上的灵活性,我们可以提炼出 operator 函数的创建 。
# 一个创建闭包的函数,实现了二元运算的逻辑_MISSING = object()def _create_binary_op(name: str, operator: str) -> Any:    """Create a binary operation function.    The `name` parameter specifies the name of the special method used for the    binary operation (e.g. `sub` for `__sub__`). The `operator` name is the    token representing the binary operation (e.g. `-` for subtraction).    """    lhs_method_name = f"__{name}__"    def binary_op(lhs: Any, rhs: Any, /) -> Any:        """A closure implementing a binary operation in Python."""        rhs_method_name = f"__r{name}__"        # lhs.__*__        lhs_type = type(lhs)        try:            lhs_method = debuiltins._mro_getattr(lhs_type, lhs_method_name)        except AttributeError:            lhs_method = _MISSING        # lhs.__r*__ (for knowing if rhs.__r*__ should be called first)        try:            lhs_rmethod = debuiltins._mro_getattr(lhs_type, rhs_method_name)        except AttributeError:            lhs_rmethod = _MISSING        # rhs.__r*__        rhs_type = type(rhs)        try:            rhs_method = debuiltins._mro_getattr(rhs_type, rhs_method_name)        except AttributeError:            rhs_method = _MISSING        call_lhs = lhs, lhs_method, rhs        call_rhs = rhs, rhs_method, lhs        if (            rhs_type is not _MISSING  # Do we care?            and rhs_type is not lhs_type  # Could RHS be a subclass?            and issubclass(rhs_type, lhs_type)  # RHS is a subclass!            and lhs_rmethod is not rhs_method  # Is __r*__ actually different?        ):            calls = call_rhs, call_lhs        elif lhs_type is not rhs_type:            calls = call_lhs, call_rhs        else:            calls = (call_lhs,)        for first_obj, meth, second_obj in calls:            if meth is _MISSING:                continue            value = meth(first_obj, second_obj)            if value is not NotImplemented:                return value        else:            exc = TypeError(                f"unsupported operand type(s) for {operator}: {lhs_type!r} and {rhs_type!r}"            )            exc._binary_op = operator            raise exc


推荐阅读