Что не так с superclass.method (object, parms)? - PullRequest
0 голосов
/ 29 марта 2012

Скажем, у меня есть этот пример кода, который я пишу для урока Python, который я провожу:

class Enum(dict):
  def __init__(self, *values):
    values = {mnemo: num
      for num, mnemo in enumerate(values)}
    dict.__init__(self, values) # ← this
  def __getattr__(self, name):
    return self[name]

Кажется, что это работает, как и ожидалось, по крайней мере, на поверхностном методе, но я вижу большелитературного времени в Интернете:

Я думаю, особенно последний более СУХОЙ, но super () будет сложнее объяснить, когда я начну использовать множественное наследование.Я хочу убедиться, что там нет никаких неприятных ошибок, на которые потом наткнуться другие люди.

1 Ответ

4 голосов
/ 29 марта 2012
  1. Я не понимаю, почему вы вообще должны избегать наследования от встроенных типов. Считалось улучшением то, что появление классов нового стиля позволило сделать это, и даже до этого стандартная библиотека предоставляла классы UserDict и UserList для получения. Конечно, в каждом конкретном случае вы должны оценивать, нужно ли вам наследование или композиция, но именно так всегда есть в ООП - здесь нет ничего особенного во встроенных типах.

  2. Я бы не рекомендовал super() в этом примере. Это полезно, только если все взаимодействующие методы имеют одинаковую подпись или, по крайней мере, взаимодействующие подписи. На мой взгляд, для одиночного наследования и множественного наследования «без бриллиантов» явный вызов методов базового класса вполне подходит. Если вы хотите получить правильные результаты в множественном наследовании с бриллиантами, вы вынуждены использовать super(), но вы должны тщательно разработать свои методы, см. Раймонд Хеттингер: «Питон super() считается супер!»

    Обычно безопасно использовать super() в случаях, когда все задействованные методы имеют абсолютно одинаковую сигнатуру, включая такие методы, как __getattr__() и __setattr__().

  3. Ваш пример класса является довольно сомнительной реализацией типа Enum, но не по какой-либо из причин, упомянутых в вашем посте. Он смешивает два пространства имен: пространство имен атрибутов dict и записи перечисления. Попробуйте Enum("clear", "update"), чтобы понять, что я имею в виду. В этом конкретном случае следующая реализация будет намного лучше:

    class Enum(object):
        def __init__(self, *values):
            vars(self).update({mnemo: num for num, mnemo in enumerate(values)})
    

    Это добавляет записи перечисления в качестве атрибутов к стандартному экземпляру, не производные от dict. В любом случае каждый пользовательский экземпляр класса имеет свой собственный словарь, а именно __dict__.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...