Сегодня днем я провел несколько часов, пытаясь найти ошибку в своем пользовательском расширении до 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,...)
Использование супер не всегда может быть лучшим. Есть много трудностей с использованием супер. Прочтите Джеймса Найт http://fuhm.org/super-harmful/ для примера.
Эта ссылка показывает (среди других вопросов), что
__init__
всех подклассов, которые используют супер, должны совпадать. Вы должны передать все аргументы, которые вы получаете, в суперфункцию. Ваш __init__
должен быть готов вызвать любой другой метод класса __init__
в иерархии.
__init__
В вашей ситуации каждый из вышеперечисленных критериев нарушен.
Джеймс Найт также говорит:
Единственная ситуация, в которой super() может быть полезным, когда вы имеют наследование алмазов. И даже то это часто не так полезно, как вы могли подумать.
Условия, при которых супер можно использовать правильно, являются достаточно обременительными, что я считаю, что суперполезность весьма ограничена. Предпочитают шаблон дизайна композиции над подклассом. Избегайте наследования алмазов, если можете. Если вы управляете иерархией объектов сверху (объектом) и снизу и используете супер последовательно, тогда вы в порядке. Но так как вы не контролируете всю иерархию классов в этом случае, я предлагаю отказаться от использования super
.
super()
- мощный инструмент, я начинаю понимать его недостатки. Спасибо за подробное указание!
Я думаю, вы пропустили передать параметр 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>>
<super>
, он вызывает AttributeError.
super
работал правильно