Haciendo super () de trabajo en Python urllib2.Request
-
20-09-2019 - |
Pregunta
Esta tarde pasé varias horas tratando de encontrar un error en mi extensión personalizada a urllib2.Request
. El problema era, como descubrí, el uso de super(ExtendedRequest, self)
, ya que es urllib2.Request
(estoy en Python 2.5) sigue siendo una clase de estilo antiguo, donde el uso de super()
no es posible.
La forma más obvia de crear una nueva clase con ambas características,
class ExtendedRequest(object, urllib2.Request):
def __init__():
super(ExtendedRequest, self).__init__(...)
no funciona. Llamándola, me quedo con AttributeError: type
planteada por urllib2.Request.__getattr__()
. Ahora, antes de empezar a pegar y copy'n toda la clase urllib2.Request
de / usr / lib / python sólo para volver a escribir como
class Request(object):
tiene alguien una idea, cómo podría lograr esto en una forma más elegante? (Con este es tener un nuevo estilo clase basada en urllib2.Request
con soporte para trabajar super()
.)
Editar Por cierto: el mencionado 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
Solución
Esto debería funcionar bien, ya que la jerarquía es simple
class ExtendedRequest(urllib2.Request):
def __init__(self,...):
urllib2.Request.__init__(self,...)
Otros consejos
El uso de súper puede no ser siempre la mejor práctica. Hay muchas dificultades con el uso de super. Leer http://fuhm.org/super-harmful/ de ejemplos.
que muestra enlaces (entre otros temas) que
- Superclases debe utilizar Super si sus subclases hacen
- Las firmas
__init__
de todas las subclases que utilizan súper deben coincidir. Debe pasar todos los argumentos que recibe a la función de super. Su__init__
debe estar preparado para llamar al método__init__
de cualquier otra clase en la jerarquía. - Nunca utilice argumentos posicionales en
__init__
En su situación, cada uno de los critera anterior se viola.
James Knight también dice:
La única situación en la que super () en realidad puede ser útil es cuando se tiene herencia diamante. e incluso a continuación, a menudo no es tan útil como que podría haber pensado.
Las condiciones bajo las cuales súper pueden ser utilizados correctamente son suficientemente onerosas, que creo que la utilidad de súper es más bien limitada. Prefiero el patrón de diseño Composición sobre subclases. Evitar la herencia de diamante si es posible. Si el control de la jerarquía de objetos de arriba (objeto) a abajo, y utilizar Super constantemente, entonces estás bien. Pero ya que usted no controla toda la jerarquía de clases, en este caso, sugeriría que se abandona el uso de super
.
Creo que se ha perdido al pasar el parámetro auto a la definición de init en la muestra. Prueba con esto:
class ExtendedRequest(object, urllib2.Request):
def __init__(self):
super(ExtendedRequest, self).__init__(self)
Lo he comprobado y parece que funciona okey:
>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>