Question

Cet après-midi, j'ai passé plusieurs heures à essayer de trouver un bug dans mon extension personnalisée à urllib2.Request. Le problème était, comme je l'ai découvert, l'utilisation de super(ExtendedRequest, self), puisque urllib2.Request est (je suis sur Python 2.5) encore une ancienne classe de style, où l'utilisation de super() n'est pas possible.

La façon la plus évidente pour créer une nouvelle classe avec les deux fonctions,

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

ne fonctionne pas. L'appel, je suis parti avec AttributeError: type soulevé par urllib2.Request.__getattr__(). Maintenant, avant que je commence et copy'n coller toute la classe urllib2.Request de / usr / lib / python juste pour réécrire comme

class Request(object):

Quelqu'un a une idée, comment je pourrais y parvenir d'une façon plus élégante? (Avec ce étant d'avoir un nouveau style classe basée sur urllib2.Request avec le soutien de travail pour super().)

Modifier Par ailleurs: AttributeError mentionné:

>>> 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
Était-ce utile?

La solution

Cela devrait bien puisque la hiérarchie est simple

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

Autres conseils

L'utilisation de super ne peut pas toujours être la meilleure pratique. Il y a beaucoup de difficultés à l'utilisation de super. Lire la http://fuhm.org/super-harmful/ pour des exemples.

ce lien montre (entre autres questions) que

  1. Superclasses doit utiliser super si leurs sous-classes font
  2. Les signatures de __init__ de toutes les sous-classes qui utilisent super doivent correspondre. Vous devez passer tous les arguments que vous recevez à la fonction super. Votre __init__ doit être prêt à appeler toute autre méthode de __init__ de classe dans la hiérarchie.
  3. Ne jamais utiliser des arguments de position dans __init__

Dans votre situation, chacun des critera ci-dessus est violée.

James Knight dit aussi,

  

La seule situation dans laquelle super ()   peut effectivement être utile est lorsque vous   ont l'héritage de diamant. Et même   alors, il est souvent aussi utile que   on aurait pu penser.

Les conditions dans lesquelles super peut être utilisé correctement sont suffisamment onéreux, que je pense que l'utilité de super est assez limitée. Préférez le modèle de conception de composition sur subclassing. Évitez l'héritage de diamant si vous le pouvez. Si vous contrôlez la hiérarchie des objets de haut (objet) vers le bas, et utilisez super constamment, alors vous êtes d'accord. Mais puisque vous ne contrôlez pas toute la hiérarchie des classes dans ce cas, je vous suggère de vous abandonner à l'aide super.

Je pense que vous avez manqué de passer le paramètre auto à la définition de init dans votre échantillon. Essayez celui-ci:

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

Je l'ai testé et il semble fonctionner Okey:

>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top