Заставить super () работать в urllib2.Request Python

1

Сегодня днем ​​я провел несколько часов, пытаясь найти ошибку в своем пользовательском расширении до urllib2.Request. Проблема заключалась, как я выяснил, в использовании super(ExtendedRequest, self), так как urllib2.Request (я на Python 2.5) все еще старый класс стиля, где использование super() невозможно.

Самый очевидный способ создать новый класс с обеими функциями,

class ExtendedRequest(object, urllib2.Request):
    def __init__():
        super(ExtendedRequest, self).__init__(...)

не работает. Вызвав его, я остался с AttributeError: type поднятым urllib2.Request.__getattr__(). Теперь, прежде чем я начну и скопирую, вставьте весь класс urllib2.Request из /usr/lib/python, чтобы переписать его как

class Request(object):

есть кто-нибудь, как я мог бы добиться этого более элегантным способом? (Для этого нужно иметь класс нового стиля на основе urllib2.Request с рабочей поддержкой super().)

Изменить: Кстати: упоминается AttributeError:

>>> class ExtendedRequest(object, urllib2.Request):
...   def __init__(self):
...     super(ExtendedRequest, self).__init__('http://stackoverflow.com')
...
>>> ABC = ExtendedRequest ()
>>> d = urllib2.urlopen(ABC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/urllib2.py", line 124, in urlopen
    return _opener.open(url, data)
  File "/usr/lib/python2.5/urllib2.py", line 373, in open
    protocol = req.get_type()
  File "/usr/lib/python2.5/urllib2.py", line 241, in get_type
    if self.type is None:
  File "/usr/lib/python2.5/urllib2.py", line 218, in __getattr__
    raise AttributeError, attr
AttributeError: type
Теги:
request
super
urllib2

3 ответа

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

Это должно работать нормально, так как иерархия проста

class ExtendedRequest(urllib2.Request):
    def __init__(self,...):
        urllib2.Request.__init__(self,...)
  • 0
    Спасибо за ответ, но я знаю это. На самом деле, я делаю именно это в данный момент. Однако я хотел использовать силу super () в некоторых аспектах, таких как множественное наследование.
  • 0
    Вся иерархия должна быть новым стилем, чтобы super работал правильно
Показать ещё 2 комментария
1

Использование супер не всегда может быть лучшим. Есть много трудностей с использованием супер. Прочтите Джеймса Найт http://fuhm.org/super-harmful/ для примера.

Эта ссылка показывает (среди других вопросов), что

  1. Суперклассы должны использовать супер, если их подклассы
  2. Подписи __init__ всех подклассов, которые используют супер, должны совпадать. Вы должны передать все аргументы, которые вы получаете, в суперфункцию. Ваш __init__ должен быть готов вызвать любой другой метод класса __init__ в иерархии.
  3. Никогда не используйте позиционные аргументы в __init__

В вашей ситуации каждый из вышеперечисленных критериев нарушен.

Джеймс Найт также говорит:

Единственная ситуация, в которой super() может быть полезным, когда вы имеют наследование алмазов. И даже то это часто не так полезно, как вы могли подумать.

Условия, при которых супер можно использовать правильно, являются достаточно обременительными, что я считаю, что суперполезность весьма ограничена. Предпочитают шаблон дизайна композиции над подклассом. Избегайте наследования алмазов, если можете. Если вы управляете иерархией объектов сверху (объектом) и снизу и используете супер последовательно, тогда вы в порядке. Но так как вы не контролируете всю иерархию классов в этом случае, я предлагаю отказаться от использования super.

  • 0
    Тем временем я просмотрел некоторые связанные вопросы в правой колонке и тоже нашел статью Джеймса Найта. Хотя я все еще думаю, что super() - мощный инструмент, я начинаю понимать его недостатки. Спасибо за подробное указание!
0

Я думаю, вы пропустили передать параметр self в определение init в своем примере. Попробуйте следующее:

class ExtendedRequest(object, urllib2.Request):
    def __init__(self):
        super(ExtendedRequest, self).__init__(self)

Я тестировал его и, похоже, работал okey:

>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
  • 0
    Да, но когда вы пытаетесь вызвать любой метод объекта <super> , он вызывает AttributeError.

Ещё вопросы

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