类本身的运算符重载

问题描述 投票:0回答:1

我觉得这段代码应该可以工作,但是第二个表达式失败了。这是为什么?

class Foo:
    @classmethod
    def __matmul__(cls, other):
        return "abc" + other


print(Foo.__matmul__("def"))  # OK
print(Foo @ "def")  # TypeError: unsupported operand type(s) for @: 'type' and 'str'

同样适用于

__getattr__

class Foo:
    @classmethod
    def __getattr__(cls, item):
        return "abc" + item


print(Foo.__getattr__("xyz")) # OK
print(Foo.xyz) # AttributeError: type object 'Foo' has no attribute 'xyz'

解决方案是使用元类

class MetaFoo(type):
    def __matmul__(cls, other):
        return "abc" + other


class Foo(metaclass=MetaFoo):
    pass


print(Foo.__matmul__("def"))  # OK
print(Foo @ "def")  # OK

这是 (C)Python 中的错误吗?

要明确的是,问题是为什么在没有元类的情况下

print(Foo @ "def")  
在第一个示例中不起作用?

python operator-overloading class-method
1个回答
0
投票

您观察到的行为不是 Python 中的错误,而是运算符重载和类方法设计在 Python 中工作方式的结果。

在第一个示例中,您已将

__matmul__
定义为类方法。虽然这允许直接在类上调用它 (
Foo.__matmul__("def")
),但它不允许对类本身使用
@
运算符。在Python中,当您使用像
@
这样的运算符时,Python会在左操作数的类中查找相应的特殊方法(在本例中为
__matmul__
)。由于
Foo
type
的实例(因为 Python 中的类是
type
的实例),Python 在
__matmul__
上查找
type
,而不是在
Foo
上。

© www.soinside.com 2019 - 2024. All rights reserved.