Вызовы иерархии методов Python std документированы?

#python #python-datamodel

#python #python-datamodel

Вопрос:

только что столкнулся с проблемой при создании подкласса dict «type». Я переопределил __iter__ method и ожидал, что это повлияет на другие методы, такие как iterkeys, keys и т.д. Потому что я полагал, что они вызывают __iter__ method для получения значений, но, похоже, они реализованы независимо, и я должен переопределить их все.

Является ли это ошибкой или намерением, чтобы они не использовали другие методы и извлекали значения отдельно?

Я не нашел в стандартной документации Python описания зависимости вызовов между методами стандартных классов. Это было бы удобно для подсчета работы и для ориентации, какие методы требуется переопределить для правильного поведения. Существует ли какая-либо дополнительная документация о внутренних элементах базовых типов / классов python?

Ответ №1:

Создайте подкласс Mapping или MuteableMapping из модуля коллекций вместо dict , и вы получите все эти методы бесплатно.

Вот пример минимального сопоставления и некоторые из методов, которые вы получаете бесплатно:

 import collections
class MinimalMapping(collections.Mapping):
    def __init__(self, *items ):
        self.elements = dict(items)
    def __getitem__(self, key):
        return self.elements[key]
    def __len__(self):
        return len(self.elements)
    def __iter__(self):
        return iter(self.elements)

t = MinimalMapping()
print (t.iteritems, t.keys, t.itervalues, t.get)
  

Для создания подкласса любого из встроенных контейнеров вы всегда должны использовать соответствующий базовый класс из модуля collections.

Комментарии:

1. Спасибо за подсказку. Я упомянул dict в качестве примера. Я ищу более общие принципы создания подклассов в Python.

2. @David Unric: Это является общим принципом.. dict etc должны выполняться как можно быстрее, а не быть легко расширяемыми — для этого предназначены базовые классы в модуле collections.

3. Скорость может быть одной из причин для создания подкласса dict вместо collections.Mapping . Излишне говорить, что я не согласен с вашим утверждением о том, что всегда создается подкласс из collections базового класса, а не встроенных. Одной из причин введения новой объектной модели в Python 2.2 было именно то, что вы могли создавать подклассы встроенных функций.

4. 1 за чтение мыслей: хотя это вообще не отвечает на письменный вопрос, автор сообщения выбрал его в качестве ответа!

Ответ №2:

Если это не указано в документации, это зависит от реализации. Другие реализации, для реализации которых CPython может повторно использовать iter метод iterkeys , и другие. Я бы не считал это ошибкой, а просто небольшой свободой для разработчиков.

Я подозреваю, что существует фактор производительности при независимой реализации методов, тем более что словари так широко используются в Python.

Итак, в принципе, вы должны их реализовать.

Комментарии:

1. Да, я предполагал, что это способ реализовать их все. Может ли кто-нибудь еще подтвердить, что это не ошибка или функция, удаленная в Pyton 3.x

Ответ №3:

Вы знаете поговорку: «Вы знаете, что происходит, когда вы предполагаете». 🙂

Они официально не документируют этот материал, потому что могут решить изменить его в будущем. Любая неофициальная документация, которую вы можете найти, просто документирует текущее поведение одной реализации Python, и полагаться на нее приведет к тому, что ваш код будет очень, очень хрупким.

Когда существует официальная документация по специальным методам, она, как правило, описывает поведение интерпретатора по отношению к вашим собственным классам, например, использование, __len__() когда __nonzero__() это не реализовано, или требуется только __lt()__ для сортировки.

Поскольку Python использует утиный ввод, вам обычно не нужно наследовать от встроенного класса, чтобы ваш собственный класс действовал как один. Итак, вы могли бы пересмотреть, действительно ли создание подклассов dict — это то, что вы хотите сделать. Вы можете выбрать другой класс, например, что-то из collections модуля, или инкапсулировать, а не наследовать. ( UserString Класс использует инкапсуляцию.) Или просто начать с нуля.

Ответ №4:

Вместо создания подклассов dict вы могли бы вместо этого просто создать make свой собственный класс, который имеет именно те свойства, которые вы хотите, без особых проблем. Вот сообщение в блоге с примером того, как это сделать. __str__() Метод в нем не самый лучший, но это легко исправимо, остальные предоставляют функциональность, которую вы ищете.