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
¿Fue útil?

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

  1. Superclases debe utilizar Super si sus subclases hacen
  2. 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.
  3. 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>>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top