Pergunta

Esta tarde, passei várias horas tentando encontrar um bug na minha extensão personalizada para urllib2.Request. O problema era, como descobri, o uso de super(ExtendedRequest, self), desde urllib2.Request está (estou no python 2.5) ainda uma aula de estilo antigo, onde o uso de super() não é possível.

A maneira mais óbvia de criar uma nova classe com os dois recursos,

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

não funciona. Chamando, eu fico com AttributeError: type criado por urllib2.Request.__getattr__(). Agora, antes de começar e copiar, colar o todo urllib2.Request classe de/usr/lib/python apenas para reescrever como

class Request(object):

Alguém tem uma ideia, como eu poderia conseguir isso de uma maneira mais elegante? (Com isto sendo ter um novo estilo classe baseada em urllib2.Request com suporte de trabalho para super().)

Editar: A propósito: o atributoError mencionado:

>>> 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
Foi útil?

Solução

Isso deve funcionar bem, pois a hierarquia é simples

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

Outras dicas

Usar o Super nem sempre é a melhor prática. Existem muitas dificuldades em usar super. Leia James Knight's http://fuhm.org/super-harmful/ por exemplo.

Esse link mostra (entre outras questões) que

  1. Superclasses devem usar super se suas subclasses fazem
  2. o __init__ Assinaturas de todas as subclasses que usam super devem corresponder. Você deve passar em todos os argumentos que recebe para a super função. Sua __init__ deve estar preparado para ligar para qualquer outra classe __init__ Método na hierarquia.
  3. Nunca use argumentos posicionais em __init__

Na sua situação, cada um dos critérios acima é violado.

James Knight também diz,

A única situação em que o super () pode realmente ser útil é quando você tem herança de diamante. E mesmo assim, muitas vezes não é tão útil quanto você poderia ter pensado.

As condições sob as quais o super podem ser usadas corretamente são suficientemente onerosas, que acho que a utilidade do super é bastante limitada. Prefira o padrão de design da composição ao longo da subclasse. Evite a herança de diamante, se puder. Se você controlar a hierarquia do objeto de cima (objeto) para baixo e usar de forma super consistente, você estará bem. Mas como você não controla toda a hierarquia de classe neste caso, eu sugiro que você abandone o uso super.

Eu acho que você perdeu para passar no parâmetro self para a definição de iniciar em sua amostra. Tente este:

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

Eu testei e parece funcionar okey:

>>> x = ExtendedRequest()
>>> super(ExtendedRequest, x)
<super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top