Вы можете полностью заменить объект внутренним методом?

1

Мы пытаемся решить следующую проблему в python 3: мы определили класс, который наследуется от list. Мы хотим включить метод, с помощью которого он может обновить себя до нового экземпляра этого класса.

Какой-то очень простой код, чтобы проиллюстрировать, что мы имеем в виду:

class test(list):
    def update(self):
        self = test(['a','b','c','d'])

x = test([1,2,3])
x.update()
print(x)

Этот код возвращает исходный список [1,2,3], который показывает, что объект x действительно не обновлялся. Есть ли способ полностью обновить объект? Нам нужно, чтобы это работало для списков разной длины.

Теги:
object
methods
replace
internal

1 ответ

4
Лучший ответ

self - это еще одна переменная. Объекты метода приводят к тому, что текущий экземпляр присваивается этому имени (так же, как другие значения назначаются другим параметрам функции), но, как и другие имена, назначение им будет изменять только те объекты, на которые ссылается имя. Другие имена, ссылающиеся на один и тот же объект, например x, не изменяются.

Это потому, что имена в коде Python похожи на теги, а self = <something else> - это как тег старого экземпляра и помещать его на другой объект. Любые другие теги, все еще прикрепленные к старому объекту, не перемещаются! Поскольку x все еще ссылается на старый экземпляр, он не увидит, что вы помещаете тег self на другой объект.

Либо ваш метод update() должен возвращать новый объект (чтобы вызывающий мог обновить свою ссылку, чтобы указать на новый объект), либо изменить список на месте (после чего все ссылки на объект будут видеть одно и то же изменение,

Возврат объекта означает, что вызывающий абонент отвечает за выполнение чего-то с возвращаемым значением:

class test(list):
    def update(self):
        return test(['a','b','c','d'])

x = test([1,2,3])
x = x.update()  # re-bind 'x' to point to the new object.
print(x)

Или вы можете назначить индексы самого списка; это изменяет то, на что указывает содержимое списка. Вы можете использовать self же, как и любую другую ссылку, поэтому x[0] = 5 изменит индекс 0, так что self[0] = 5. И если вы назначаете срез, вы можете сразу изменить несколько индексов. Локус идентификатора [:] позволяет вам сразу изменять все индексы, и вы можете назначить больше или меньше значений для увеличения или сокращения списка. Присвоение self[:] изменяет все индексы и позволяет вам изменять все индексы, указывая на любое количество разных значений.

Так:

class test(list):
    def update(self):
        self[:] = ['a', 'b', 'c', 'd']


x = test([1,2,3])
x.update()
print(x)  # The x reference to the same list will see the change too

Вышеуказанное заменяет все индексы значениями в другом списке. Все ссылки на экземпляр будут видеть изменение; как и self и x, и любые другие подобные ссылки.

Демонстрация того, что это означает:

>>> class test(list):
...     def update(self):
...         self[:] = ['a', 'b', 'c', 'd']
...
>>> x = test([1, 2, 3])
>>> y = x   # another reference to the same object
>>> x
[1, 2, 3]
>>> y
[1, 2, 3]
>>> x.update()  # update the list in-place
>>> x   # visible here
['a', 'b', 'c', 'd']
>>> y   # and here!
['a', 'b', 'c', 'd']

Ещё вопросы

Сообщество Overcoder
Наверх
Меню