在Python中动态覆盖__function__

时间:2013-11-03 06:22:11

标签: python

假设我想在Python类中覆盖像__int__这样的函数,这样我就可以这样做。

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

a = A()
print int(a)

我希望它会输出“1”而不是产生此错误消息

  

TypeError:int()参数必须是字符串或数字,而不是'A'

__int__成为类中内置的方法时,它按预期工作。为什么? (任何双下划线函数都存在此问题)

2 个答案:

答案 0 :(得分:3)

这似乎是__魔术方法中的一点魔力。与其他方法不同,当隐式调用时,它们不会在类实例上查找。

有充分证据表明他们没有使用__getattribute__魔术方法解决(如果他们这样做,那将是一个很好的悖论,因为__getattribute__必须调用自己来解析自己的名字)。但不检查实例让我感到惊讶。

这里有一点讨论,在标题“特殊方法查找”下: http://segfaulthunter.github.io/articles/biggestsurprise/

  

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

我很想知道是否有其他人可以提供更详细的解释。

答案 1 :(得分:1)

如果我们暂时忽略您询问特殊方法,那么您的代码将如下所示:

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

写得更清楚:

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中往往效果最好。 ; - )