2017-01-18 2 views
0

Я хотел бы иметь класс с методом, который создает новый экземпляр своего суперкласса (родительский класс a.k.a.).Как создать экземпляр класса из экземпляра этого класса?

Кроме того, я хотел бы подклассы класса, описанного выше, и этот подкласс наследует метод, а затем сможет использовать этот метод для создания большего количества экземпляров собственного подкласса.

Но, когда я пытаюсь сделать это, как это ...

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.make_new_instance()' if 's' является экземпляром подкласса (и это имя, которое вы дали staticmethod). – 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

Приятный улов! Списки и dicts почти всегда являются плохими идеями для аргументов по умолчанию. Ни одно решение не является моим fav, но если на самом деле не нужно иметь аргумент по умолчанию, можно просто отказаться от него. – Alan

+0

Проблема _is_ с методом базового класса makeNew. Когда он вызывает 'self .__ class __()', он ссылается на подкласс, если он вызывается с его аргументом 'self', установленным в экземпляр подкласса (как в случае с' s.makeNew() ', как показано в вопросе). – martineau

+0

@martineau: Я не уверен, почему это проблема. Было бы довольно странно, если бы вызов 'makeNew' в подклассе дал вам экземпляр суперкласса, поэтому я бы назвал это ожидаемое поведение, а не проблемой. – zondo

 Смежные вопросы

  • Нет связанных вопросов^_^