#python #python-3.x #list #class #copy
#python #python-3.x #Список #класс #Копировать
Вопрос:
Я смущен следующими результатами, поскольку, насколько я понимаю, [:]
выполняется неглубокая копия, и когда вы меняете либо старый список, либо недавно скопированный, оба они должны измениться? (Это было показано на одном из курсов Coursera, которым я следую). Также, если я хочу объявить список как переменную класса, с намерением, которое является значениями по умолчанию, и дочерние классы могут переопределить его / изменить его, если захотят, но родительский должен оставаться неизменным, это правильный способ сделать это? Большое спасибо за вашу помощь.
oldlist=[["a"],"b"]
newlist= oldlist[:]
newlist[0]="2"
oldlist[0].append(["c"])
print(oldlist) #printed out [['a', ['c']], 'b']
print(newlist) #printed out ['2', 'b']
class Book():
similar_books =['book one','book two']
def __init__ (self, n, l):
self.name= n
self.like = l
self.similar_books = self.similar_books[:] # is it the correct way to do so?
Комментарии:
1. Я думаю, вы получаете желаемое поведение из кода. вы можете продолжить таким же образом.
2. Я думаю, вам следует вместо этого использовать Google: «статическое свойство в pyhton»..
Ответ №1:
Согласно официальной документации Python, фрагмент списка является мелкой копией. В этом случае мелкая копия создает новый составной объект, а затем вставляет ссылку на исходный содержащийся объект. Когда «2» присваивается индексу [0] newlist, ссылка перезаписывается, и newlist больше не является составным объектом. Если бы вы добавили только [«c»] к индексу [0] oldlist, вы получили бы ожидаемое поведение при мелком копировании.
Для второй части вашего вопроса объекты, инициализированные внутри родительского класса (но вне конструктора), являются статическими и не будут переопределены или изменены дочерними классами. Из любопытства, почему бы просто не назначить [‘book one’,’book two’] непосредственно self.similar_books в методе init?
class Book(object):
def __init__(self, n, l):
self.name = n
self.like = l
self.similar_books = ['book one', 'book two']
class FavouriteBook(Book):
def __init__(self):
super().__init__('name', 'like')
self.similar_books = ['book_3']
Комментарии:
1. Спасибо. Идея заключается в том, что если есть дочерний класс, по умолчанию дочерний класс будет иметь
similar_books=['book one','book two']
, но дочерний класс также может сделать что-то подобное, чтобы определить свой собственныйsimilar_book
атрибут :class FavouriteBook(Book): similar_books = ['book3']
. Таким образомFavouriteBook
, класс имеет book3 вместо book 1 и 2 какsimilar_book
. Это правильный путь?2. Инициализация
similar_books=['book one','book two']
перед конструктором является избыточной. Я предполагаю, что вы вызовете суперконструктор для присвоения имени и типа дочернему классу,super().__init__('name', 'like')
. Как только вы вызываете суперконструктор, дочерний класс наследует similar_books , который затем можно переопределитьself.similar_books = ['book_3']
. Ответ обновлен примером.