Расширение типов путем подкласса в 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 
  • Google App Engine: task_retry_limit не работает?
  • Функции отправки на Python (PEP 443)
  • Как временно скрыть stdout или stderr во время запуска unittest в Python
  • Отладка функции в python
  • Zen of Python: Ошибки никогда не должны проходить молча. Почему zip работает так, как он делает?
  • получение границы элемента из другого списка
  • из . импорт * из модуля
  • Значение цифр после NaN в десятичном объекте Python
  • Как выполнить оператор «if-for» в python?
  • Объект MyClass не имеет атрибута '__getitem__'
  • Какое простейшее приложение для сокращения URL-адресов можно написать в python для Google App Engine?
  •  
    Interesting Posts for Van-Lav

    Чтение электронных писем с помощью imaplib – Ошибка «Получено более 10000 байт»

    Есть ли разница между «foo is None» и «foo == None»?

    Получение исходного двоичного представления файла в Python

    Регулярные выражения Python для реализации строкового unescaping

    UnicodeDecodeError: кодек ascii не может декодировать байт в 0xc3 в позиции 304: порядковый номер не в диапазоне (128)

    Как программно получить контрольную сумму MD5 файла Amazon S3 с помощью boto

    Невозможно передать значение тензора заполнителя

    Как обновить Python?

    AttributeError при использовании «import dateutil» и «dateutil.parser.parse ()», но при использовании «from dateutil import parser» нет проблем,

    Обновить метку элемента меню tkinter?

    Ошибка Postgres SSL SYSCALL: обнаружен EOF с помощью python и psycopg

    Получить cookie из CookieJar по имени

    Python: Разница между: = и "is not"

    Перевод функции для нахождения всех разделов набора из Python в Ruby

    Проверьте, имеет ли пользователь разрешение в пирамиде (пилоны 2)?

    Python - лучший язык программирования в мире.