知道是否在对象上调用了+或__add__

cjr*_*eds 7 python

在Python中,我可以重载对象的__add__方法(或其他双下划线又名"dunder"方法).这允许我在使用Python运算符时为我的对象定义自定义行为.

是否可以从dunder方法中了解该方法是通过+还是通过__add__

例如,假设我想创建一个打印的对象,"+"或者"__add__"取决于是否+使用或是否__add__直接调用.

class MyAdder(object):
    def __add__(self, other):
        print method_how_created()
        return 0


MyAdder() + 7
# prints "+", returns 0

MyAdder().__add__(7)
# prints "__add__", returns 0
Run Code Online (Sandbox Code Playgroud)

除非有一些神奇的存在method_how_created,是否有符号与dunder方法的规范映射?我知道有一些列表,例如http://www.python-course.eu/python3_magic_methods.php或基于解析operator模块文档字符串的解决方案,如下所述:按符号访问运算符函数.有没有办法在函数名和符号之间找到一个比解析文档字符串或手动创建列表更少hacky的映射?

Die*_*Epp 5

是的,但你可能不想这样做,因为这是一个坏主意.您必须检查解释器堆栈.出于显而易见的原因,如果从C调用代码,这将无效.以下是代码:

import inspect
import dis

class A(object):
    def __add__(self, other):
        fr = inspect.getouterframes(
            inspect.currentframe(), 1)[1][0]
        opcode = fr.f_code.co_code[fr.f_lasti]
        # opcode = ord(opcode) # Uncomment for Python 2
        is_op = opcode == dis.opmap['BINARY_ADD']
        if is_op:
            print('Called with +')
        else:
            print('Called with __add__')

A() + 1
A().__add__(1)
Run Code Online (Sandbox Code Playgroud)

这是经过测试并适用于Python 3,并且只需对Python 2稍作修改即可.