2017-01-18 168 views
0

我想要创建一个新的超类实例(a.k.a.“parent”class)的方法。如何从该类的实例创建类的实例?

此外,我想子类上面描述的类,并有这个子类继承该方法,然后能够使用该方法创建自己的子类更多的实例。

但是,当我尝试做这样......

class Superclass: 
    def makeNew(self): 
     return self.__class__() #this isn't making a clean copy 

class Subclass(Superclass): 
    def __init__(self, value = [1]): 
     self.value = value 

    def setValue(self, newValue): 
     self.value[0] = newValue 

if __name__ == "__main__": 
    s = Subclass() 
    s.setValue(5) 
    other = s.makeNew() 
    print(s.value) 
    print(other.value) 

我得到

>>> [5] #s.value 
>>> [5] #other.value 

为什么不self.__class__()给我父的全新副本?

我在做什么错?我如何创建我想要的课程?

+0

你认为什么是“干净的副本”?你取而代之的是什么?无论如何,这样做的另一种方法是在子类中定义一个'@ staticmethod',它将创建并返回新的实例。如果's'是子类的一个实例(这就是你给静态方法的名字),你可以用's.make_new_instance()'调用它。 – martineau

+0

“干净的拷贝”我的意思是它与原来的's'完全分开。它应该打印'[5] \ n [1]' –

回答

4

这不是你的makeNew方法的问题;这是您的__init__的问题。当你有一个可变的默认参数时,修改该值将修改你所有未来的默认值。你应该做的是这样的:

def __init__(self, value=None): 
    if value is None: 
     value = [1] 
    # ... 

这样,每个新的实例创建一个新的列表,而不是更多的引用到同一个列表。

在附注中,看起来并不需要value作为列表。当然,其他代码在这里没有显示可能需要它,但如果这是所有的代码,所有你需要的是self.value = ...。既然你现在重新指定self.value而不是修改它,你可以使用默认参数。

+0

好的!列表和字典对于默认参数几乎总是一个坏主意。没有解决方案是我最喜欢的,但如果它不需要有一个默认参数,可以简单地将它完全放弃。 – Alan

+0

使用'makeNew'基类方法解决问题。当它调用'self .__ class __()'时,如果它的'self'参数被设置为一个子类实例(如's.makeNew()'那样)调用子类,如问题所示。 – martineau

+0

@martineau:我不知道为什么这是一个问题。如果在子类上调用'makeNew'给了你一个超类的实例,那么我会调用那个期望的行为,而不是一个问题。 – zondo