Расширение типов путем подкласса в Python

Это извлечено из 4-го издания Learning Python. Его функция заключается в подклассе с использованием списка. Но я не понимаю list.__init__([]) строк 5 list.__init__([]) , пожалуйста, помогите. Код работает даже тогда, когда я прокомментировал эту строку кода. Зачем?

 ### file: setsubclass.py class Set(list): def __init__(self, value = []): # Constructor list.__init__([]) # Customizes list self.concat(value) # Copies mutable defaults def intersect(self, other): # other is any sequence res = [] # self is the subject for x in self: if x in other: # Pick common items res.append(x) return Set(res) # Return a new Set def union(self, other): # other is any sequence res = Set(self) # Copy me and my list res.concat(other) return res def concat(self, value): # value: list, Set . . . for x in value: # Removes duplicates if not x in self: self.append(x) def __and__(self, other): return self.intersect(other) def __or__(self, other): return self.union(other) def __repr__(self): return 'Set:' + list.__repr__(self) if __name__ == '__main__': x = Set([1,3,5,7]) y = Set([2,1,4,5,6]) print(x, y, len(x)) print(x.intersect(y), y.union(x)) print(x & y, x | y) x.reverse(); print(x) x 

4 Solutions collect form web for “Расширение типов путем подкласса в Python”

Код в книге содержит ошибку. Я отправил исправления в книги О'Рейли, которые вы можете прочитать вместе с ответом авторов на этой странице (поиск 982). Вот небольшой фрагмент его ответа:

Эта кодовая строка, по-видимому, присутствовала в книге со 2-го издания (2003–10 лет назад!), И до сих пор осталась без внимания сотнями тысяч читателей

В list.__init__([]) строк list.__init__([]) отсутствует аргумент , и комментирование его не имеет никакого значения, кроме как немного ускорить вашу программу. Вот исправленная строка:

  list.__init__(self, []) 

При вызове методов, которые не являются статическими методами или методами класса непосредственно в объектах класса, обычно явно неявный первый аргумент self должен предоставляться явно. Если строка будет исправлена ​​так, она будет следовать хорошей практике, о которой говорит Антонис в своем ответе. Другой способ исправить строку можно было бы с помощью super , что снова делает неявный аргумент self .

  super(Set, self).__init__([]) 

Код в книге предоставляет другой пустой список ( [] ) как аргумент self , который заставляет этот список снова инициализироваться, после чего он быстро собирает мусор. Другими словами, вся строка – это мертвый код.

Чтобы убедиться, что исходная строка неэффективна: временно измените [] в list.__init__([]) на непустой список и обратите внимание, что полученный экземпляр Set не содержит эти элементы. Затем вставьте self в качестве первого аргумента и обратите внимание, что элементы в списке теперь добавляются в экземпляр Set .

Вы имеете в виду эту линию?

  list.__init__([]) 

Когда вы переопределяете метод __init__ любого типа, рекомендуется всегда называть унаследованный метод __init__ ; то есть метод __init__ базового класса. Таким образом вы выполняете инициализацию родительского класса и добавляете код инициализации, специфичный для дочернего класса.

Вы должны следовать этой практике, даже если вы уверены, что __init__ родителя ничего не делает, чтобы обеспечить совместимость с будущими версиями.

Обновление: как объяснил Лауритц в другом ответе, линия

  list.__init__([]) 

неправильно. См. Его ответ и другие ответы для большего.

Вы имеете в виду list.__init__([]) ?

Он вызывает базовый инициализатор из инициализатора подкласса. Ваш подкласс заменил инициализатор базового класса своим.

В этом случае комментирование этого происходит, потому что несвязанный инициализатор был вызван с пустым списком вместо self и, следовательно, является no-op. Вероятно, это ошибка от имени авторов.

Но в целом хорошая идея – убедиться, что базовый класс выполнил свой код инициализации при подклассе. Таким образом, все внутренние структуры данных, основанные на методах базового класса, были настроены правильно.

Эта строка похожа на создание конструктора __init__ в классе Set, который вызывает его конструктор базового класса.

Возможно, вы уже это видели:

 class Set(list): ... def __init__(self, *args, **kwargs): super(Set, self).__init__(args, kwargs) # do something additional here 
  • Функции отправки на Python (PEP 443)
  • Нечеткий текстовый поиск python
  • Cesar's Cipher с использованием python, может немного помочь
  • ImportError: PyCapsule_Import не смог импортировать модуль "pyexpat"
  • Демистификация эффективности sharectypes
  • «Pythonic» метод для синтаксического анализа целых целых чисел, разделенных запятыми, в список целых чисел?
  • Как передать параметры в RequestHandler?
  • Вход в Google+ - поток на стороне сервера - Python - Google App Engine
  • Python - лучший язык программирования в мире.