我正在尝试使用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
的参数会覆盖第一次调用的参数。我的猜测是a
和b
是对同一个静态类TestClass的引用,而我的deepcopy也没有帮助,因为它对静态类没有意义。
我如何调整__new__
的{{1}}和__init__
,以便我实际创建新实例(即print语句应该打印1而不是2)?
(Python 3.5)
编辑/小澄清:我实际上不希望TestClass是静态的(如果这是正确的术语),但我的非功能性实现似乎产生类似静态类的东西。
解决方案
感谢Kay,以下代码有效:
TestClass
答案 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!