Faire du travail super () en Python urllib2.Request
-
20-09-2019 - |
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
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
- Superclasses doit utiliser super si leurs sous-classes font
- 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. - 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>>