メタクラスと__getattribute__()
演算子オーバーロードがどう動いているのかを確かめるため、いろいろ意地悪なサンプルを書いてみる。
class MyType(type): def __init__(self, name, bases, dict): type.__init__(self, name, bases, dict) self.__add__ = lambda self, rhs: 1 def __getattribute__(self, name): if name == '__add__': return lambda self, rhs: 2 return type.__getattribute__(self, name) class Foo(object): def __metaclass__(name, bases, dict): return MyType(name, bases, dict) f = Foo() # Prints "2" print f.__class__.__add__(f, 0) # "1"? or "2"? print f + 0
とか
class MyType(type): def __init__(self, name, bases, dict): type.__init__(self, name, bases, dict) @property def __add__(self): return lambda self, rhs: 0 class Foo(object): def __metaclass__(name, bases, dict): return MyType(name, bases, dict) f = Foo() # Prints "0" print f.__class__.__add__(f, 0) # Does this work? print f + 0
とか。
最初の例は 1 を出力し、2 つ目の例は
Traceback (most recent call last): File "/tmp/test.py", line 17, in <module> print f + 0 TypeError: unsupported operand type(s) for +: 'Foo' and 'int'
となる。
意外性があるという意味で謎な仕様だと思った。