魔术方法可以在课外重写吗? 当我做这样的事情时
def __int__(x):
return x + 5
a = 5
print(int(a))
它打印'5'而不是'10'。我做错了什么或者魔术方法不能在课外被覆盖吗?
答案 0 :(得分:2)
简短回答;不是真的。
你不能随意改变int()
内置函数(*内部调用__int__()
)对int
(s)等任意内置类型的行为。
您可以但是会更改自定义对象的行为,如下所示:
示例:强>
class Foo(object):
def __init__(self, value):
self.value = value
def __add__(self, other):
self.value += other
def __repr__(self):
return "<Foo(value={0:d})>".format(self.value)
<强>演示:强>
>>> x = Foo(5)
>>> x + 5
>>> x
<Foo(value=10)>
这会覆盖两件事,并实现两种特殊方法:
__repr__()
调用的repr()
__add__()
由+
运营商调用。 更新:根据上述评论; techincally你可以重新定义内置函数int
;例如:
def int(x):
return x + 5
int(5) # returns 10
但不建议这样做,并且不会更改对象x
的整体行为。
更新#2:您无法更改bultin类型行为的原因(未修改基础来源或使用Cuthon或ctypes )是因为与Homoiconic Languages(参见:Homoiconicity )不同,Python中的内置类型不会向用户公开或变更。 - 即便如此,我还不确定你能用Cython / ctypes;但原因问题是&#34;你为什么要这样做?&#34;
更新#3:请参阅Data Model上的Python文档(例如 object.__complex__
)。
答案 1 :(得分:1)
您可以重新定义顶级__int__
功能,但没有人会调用它。
正如Data Model文档中所暗示的,当您撰写int(x)
时,会调用x.__int__()
,而不是__int__(x)
。
即使这不是真的。首先,__int__
是一种特殊方法,这意味着它可以调用type(x).__int__(x)
而不是x.__int__()
,但这并不重要。其次,除非你给它一些不是__int__
的东西(并用单参数形式称它),否则不需要调用int
。所以,它可能就像是这样写的:
def int(x, base=None):
if base is not None:
return do_basey_stuff(x, base)
if isinstance(x, int):
return x
return type(x).__int__(x)
所以,没有办法改变int(5)
将会做什么......当然,只需用同名的不同内置/全局/本地函数来遮蔽内置int
函数。< / p>
但是如果你想改变int(5.5)
怎么办?这不是int
,所以它会调用float.__int__(5.5)
。所以,我们所要做的就是monkeypatch,对吧?
嗯,是的,除了Python允许内置类型是不可变的,并且CPython中的大多数内置类型都是。所以,如果你尝试一下:
>>> _real_float_int = float.__int__
>>> def _float_int(self):
... return _real_float_int(self) + 5
>>> _float_int(5.5)
10
>>> float.__int__ = _float_int
TypeError: can't set attributes of built-in/extension type 'float'
但是,如果您要定义自己的类型,那就是另一个故事:
>>> class MyFloat(float):
... def __int__(self):
... return super().__int__() + 5
>>> f = MyFloat(5.5)
>>> int(f)
10