#python
#python
Вопрос:
У меня есть следующий код:
class Hello(object):
def __init__(self, names):
self.names = names
def getnames(self):
return self.names
if __name__ == "__main__":
names = ['first', 'middle', 'last']
ob = Hello(names)
a = ob.getnames()
print a
a.remove('first')
print a
print ob.getnames()
Ниже приведен вывод:
['first', 'middle', 'last']
['middle', 'last']
['middle', 'last']
Это потому, что метод getnames является изменяемым? Или, может быть, здесь происходит что-то еще. Кто-нибудь может объяснить?
Как мне заставить метод возвращать исходный список?
Ответ №1:
В Python присваивание никогда не создает копию структуры данных. Это только заставляет имя ссылаться на значение. Кроме того, вызов функции по существу присваивает фактические аргументы именам аргументов. Таким образом, в вашем коде ничего не копируется. Имена a
и ob.names
относятся к одному и тому же списку. Если вы хотите иметь две копии списка (исходную и одну для изменения), то в какой-то момент вам нужно сделать копию. Вам нужно будет решить, где это имеет наибольший смысл.
Вы можете скопировать список несколькими различными способами: list(L)
или L[:]
являются наиболее распространенными способами.
Ответ №2:
getnames
вернуть копию:
def getnames(self):
return self.names[:]
Комментарии:
1. ИМХО, это слишком поздно. Исходный список, с помощью которого был создан объект, может быть изменен вне этого класса, который также изменится
self.names
, что является просто ссылкой на исходный список. Лучше назначитьself.names = names[:]
in__init__
. Затем копия выполняется один раз, при создании объекта, и Нет никаких шансов, что в течение срока службы объекта произойдут плохие вещи (т. Е. Внешние изменения).2. Да, это правда, но вы также хотели бы, чтобы метод выдавал копию. Как если бы вы этого не сделали, вы бы столкнулись с проблемой, с которой столкнулся OP. И это то, что я написал ответ, чтобы исправить.
3. Справедливое замечание. Он должен быть скопирован в обоих местах, чтобы защититься от обоих видов непреднамеренных изменений.
Ответ №3:
Имя a
ссылается на тот же массив, в котором хранится ob.names
. Если вы меняете a
, вы меняете ob.names
, потому что они оба ссылаются на одно и то же.