无法通过覆盖__new __

时间:2015-12-02 22:55:27

标签: python

我正在尝试使用Python的__new__,以便在实例化类时返回与实际对象实例不同的内容(无论是否聪明是一个不同的讨论)。下面是一个最小的示例,其中我从__new__返回两个类实例的列表,而不是实际的类实例。

from copy import deepcopy

class TestClass:

    def __new__(self, param=None):

        self.__init__(self, param=param)

        return [deepcopy(self), deepcopy(self)]

    def __init__(self, param=None):
        self.param = param


if __name__ == '__main__':
    a = TestClass(param=1)
    b = TestClass(param=2)
    print(a[0].param) #  prints 2!

但是,似乎我无法使用此方法创建实际的对象实例,如最小示例中所示。 print语句应打印1,但打印2,这意味着传递给第二次调用TestClass的参数会覆盖第一次调用的参数。我的猜测是ab是对同一个静态类TestClass的引用,而我的deepcopy也没有帮助,因为它对静态类没有意义。

我如何调整__new__的{​​{1}}和__init__,以便我实际创建新实例(即print语句应该打印1而不是2)?

(Python 3.5)

编辑/小澄清:我实际上不希望TestClass是静态的(如果这是正确的术语),但我的非功能性实现似乎产生类似静态类的东西。

解决方案

感谢Kay,以下代码有效:

TestClass

2 个答案:

答案 0 :(得分:3)

您正在调用__new__ self的第一个参数,但它实际上是类,通常称为cls。所以你写的是课,而不是实例。

要实际使用两个实例:

class X(object):
    def __new__(cls, param):
        self1 = object.__new__(cls)
        self1.__init__(param)
        self2 = object.__new__(cls)
        self2.__init__(param)
        return self1, self2

你不能使用deepcopy,因为它会调用X.__new__()(没有param参数),这将导致循环。

答案 1 :(得分:3)

如果对param使用正确的参数,则会突出显示导致__new__在类范围内共享的特定问题。正如@Kay在他的回答中提到的,__new__接受一个类作为第一个参数,而不是实例。

class Foo(object):
    def __new__(cls, param):
        cls.__init__(cls, param=param)

这是错误,因为随后__init__在需要实例时获得了一个类。

def __init__(self, param):
    # remember that `self` here is `Foo`! so...
    self.param = param
    # ...means Foo.param = param, setting it class-wide!