为什么 __truediv__ 没有被调用?

The*_*nnu 0 python class

我做了一个名为 的课程Emulate。它接受一个对象并接受该对象的属性。

class Emulate:
    def __init__(self, obj):
        for attr in dir(obj):
            if attr != '__class__':
                setattr(self, attr, getattr(obj, attr))
Run Code Online (Sandbox Code Playgroud)

现在,我想模拟整数1

one = Emulate(1)
Run Code Online (Sandbox Code Playgroud)

/但是,我在尝试划分时无法使用:

print(one / 2)
Run Code Online (Sandbox Code Playgroud)

给出TypeError: unsupported operand type(s) for /: 'Emulate' and 'int'.

但是,如果我明确调用__truediv__

print(one.__truediv__(2))
Run Code Online (Sandbox Code Playgroud)

它工作正常,0.5作为输出给出。

这里发生了什么?我以为x / yx.__truediv__(y).

注意:这不仅仅适用于除法。所有“魔法方法”都会发生这种情况。

che*_*ner 5

魔术方法是在类上查找的,而不是在单个对象上查找的。您的Emulate类没有定义Emulate.__truediv__,而是添加一个实例属性,其值是在值method-wrapper上找到的int

当您尝试使用 时one / 2,查找Emulate.__truediv__失败。

当您尝试使用 时one.__truediv__,实例属性的查找会成功并生成一个方法包装器,可以将其2作为其参数进行调用,从而给出观察到的结果。

您可以在生成的字节代码中看到这一点:

>>> dis.dis('print(one/2)')
  1           0 LOAD_NAME                0 (print)
              2 LOAD_NAME                1 (one)
              4 LOAD_CONST               0 (2)
              6 BINARY_TRUE_DIVIDE
              8 CALL_FUNCTION            1
             10 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

在这里,操作码BINARY_TRUE_DIVIDE负责尝试使用 引用的值的类型来查找必要的方法one

>>> dis.dis('print(one.__truediv__(2))')
  1           0 LOAD_NAME                0 (print)
              2 LOAD_NAME                1 (one)
              4 LOAD_METHOD              2 (__truediv__)
              6 LOAD_CONST               0 (2)
              8 CALL_METHOD              1
             10 CALL_FUNCTION            1
             12 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

在这里,对象上的显式方法查找one会生成您创建的实例属性的值__truediv__