Fazendo super () funcionar no urllib2.request de Python
-
20-09-2019 - |
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
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
- Superclasses devem usar super se suas subclasses fazem
- 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. - 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>>