Заставить super () работать в urllib2.Request Python - PullRequest
1 голос
/ 15 февраля 2010

Сегодня днем ​​я потратил несколько часов, пытаясь найти ошибку в моем собственном расширении до 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

Ответы [ 3 ]

1 голос
/ 15 февраля 2010

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

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

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

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

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

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

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

1 голос
/ 15 февраля 2010

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

class ExtendedRequest(urllib2.Request):
    def __init__(self,...):
        urllib2.Request.__init__(self,...)
0 голосов
/ 15 февраля 2010

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

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

Я проверил это, и похоже, что все в порядке:

>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
...