覆盖__new__疑惑

时间:2012-05-11 13:38:39

标签: python python-3.x

我会尝试简化这里的情况,当覆盖__new__如下所示我不知道调用超级__new__来完成这项工作的正确方法时,我做得不错或是有没有其他方法这样做? super().__new__(cls)没有像我预期的那样产生正确的结果

我是一名蟒蛇初学者,请耐心等待,我的C ++流利

import weakref

class A(str):
    def __init__(self,s):self.a=s
class B(str):
    def __init__(self,s):self.b=s

class P(A,B):
    manifest=weakref.WeakValueDictionary()
    def __new__(cls,a,b):
        o=P.manifest.get(a+b)
        if not o:
            print(a,b,super(P,cls))
            #i thought this first should be used because __init__ puts the values in
            #and we index the manifest with parameters [a+b]
            #o=super().__new__(cls)#produces unique results for all requests?!?
            #so i called like this and it works (either with a or b)
            o=super().__new__(cls,a)#why favoring a over b?
            #o=super().__new__(cls,b)#why favoring b over a?
            #o=super().__new__(cls,a,b)#its an error (of coz)
            P.manifest[a+b]=o
        print("using",id(o))
        return o
    def __init__(self,a,b):
        A.__init__(self,a)
        B.__init__(self,b)

p=P("a","b")
q=P("a","b")
r=P("a","x")
print(id(p),id(q),id(r))

1 个答案:

答案 0 :(得分:1)

我怀疑(但我不确定)您是否试图在两个超类上调用__new__,即AB。最好的方法取决于很多事情。

P.__new__的目的是返回P的实例。这就是你应该创造的东西。这确实是super().__new__(cls,a)将要执行的操作,因此应该可以正常工作,但是,您也可以直接调用str.__new__(cls, a)

通常你实际上是在调用object.__new__,但是由于你从str继承了你不能这样做,它会告诉你在这种情况下它是不安全的。

如果您确实想使用super()(并且有时这是一个好主意),您通常应该在所有类中使用它,因此应该在A中使用它B也是__new__,不仅在__init__,还在class A(str): def __init__(self, s): super().__init__(s) self.a = s def __new__(cls, s): return super().__new__(cls, s) class B(str): def __init__(self, s): super().__init__(s) self.b = s def __new__(cls, s): return super().__new__(cls, s)

__new__

但是,由于P不具有相同的功能配置文件,因此这会成为问题,因为P需要两个参数。这可以表明您的解决方案可能不是最好的解决方案。特别是因为P是一个以两个字符串作为参数的字符串,所以没有多大意义。在上一个问题中,您谈到了多态性,这是一种在某种程度上打破这种多态性的模式,因为P没有与A和B相同的API,因此不能互换使用。

结果是我怀疑子类化是错误的解决方案。此外,我猜你正在尝试缓存对象,以便创建具有相同参数的新对象实际上将返回相同的对象。我建议您改为使用工厂方法,而不是覆盖{{1}}。