Вопрос

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

Решение

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

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

Другие советы

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

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

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

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

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

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

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

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

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

Я протестировал его, и он, кажется, работает нормально:

>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top