在Python中动态覆盖__函数__

4
假设我想在Python类中覆盖函数,比如__int__,以便我可以像这样做某些操作。
class A(object):
    def __init__(self):
        self.__int__ = lambda: 1

a = A()
print int(a)

我希望在这里输出“1”,而不是产生这个错误消息
“int()”类型错误:参数必须是字符串或数字,而不是“A”。
当__int__变成类内置的方法时,它按预期工作。为什么? (这个问题也存在于任何双下划线函数中)

回复:重复问题,主题相似,但这是一个更简洁和通用的问题版本。 - Mike
2
是的,但答案是一样的。 - BrenBarn
快速回答:你不能。稍微详细的回答:为什么你想要这样做呢? - Lennart Regebro
好奇心。我在项目中尝试一个设计想法,遇到了这个问题,让我感到困惑,所以我问了一下。这不就是 SO 的用处吗? - Mike
@Mike:不,那非常好。 - Lennart Regebro
2个回答

3
似乎这是__魔术方法中的又一个神奇之处。与其他方法不同的是,当隐式调用时,它们不会在类实例上进行查找。
虽然已经有文档说明它们不会通过__getattribute__魔术方法来解析(如果它们这样做会产生一个很好的悖论,因为__getattribute__将必须调用自身来解析自己的名称)。但是不检查实例让我感到惊讶。
这里讨论了一下,标题是“特殊方法查找”: http://segfaulthunter.github.io/articles/biggestsurprise/

对于新式类的实例,所有隐式完成的特殊方法查找都在类结构中完成。因此更改实例的__str__属性不会影响str()的结果。但是,从实例显式获取属性会给您实例中的方法。

我将很好奇是否还有其他人能够提供更详细的解释。

1
如果我们暂时不考虑你询问特殊方法的情况,那么你的代码将如下所示:
class A(object):
    def __init__(self):
        self.a_fun = lambda: 1

这样写更清晰:

Is written more clearly like this:

class A(object):
    def __init__(self):
        self._int = 1

    def a_fun(self):
        return self._int

生成的代码不是完全相同的,但足够接近,以至于没有太大区别。唯一的区别是必须将“_int”名称作为属性查找。
但如果我们现在将其改回成为特殊方法,它看起来像这样:
class A(object):
    def __init__(self):
        self.__int__ = lambda: 1

vs:

class A(object):
    def __init__(self):
        self._int = 1

    def __int__(self):
        return self._int

现在有一个非常大的区别:第二个变量可以工作,而第一个不能。这是因为特殊方法总是在类上查找,而不是实例上查找。这是按设计来的。所以,与其试图聪明地写代码,不如写出清晰易懂的代码,在Python中这通常是最好的做法。;-)

生成的代码并不完全相同,您能详细说明一下吗? - Mike
我并不想聪明机智。更别提它如何牺牲可读性了。 - Mike
@Mike:我已经详细说明了:唯一的区别是必须将_int名称作为属性查找。 - Lennart Regebro
你做了。我错过了那个。谢谢你的回复。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接