【问题标题】:Making super() work in Python's urllib2.Request使 super() 在 Python urllib2.Request 中工作
【发布时间】:2011-01-17 01:03:09
【问题描述】:

今天下午,我花了几个小时试图在 urllib2.Request 的自定义扩展中找到一个错误。正如我发现的那样,问题是super(ExtendedRequest, self) 的使用,因为urllib2.Request (我在Python 2.5 上)仍然是一个旧样式类,其中super() 的使用是不可能的。

创建具有这两种功能的新类的最明显方法,

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

不起作用。调用它,我留下了由urllib2.Request.__getattr__() 提出的AttributeError: type。现在,在我开始复制之前,从 /usr/lib/python 复制整个 urllib2.Request 类,以便将其重写为

class Request(object):

有人有什么想法,我怎样才能以更优雅的方式实现这一目标? (this 有一个基于 urllib2.Requestnew-style 类,并为 super() 提供工作支持。)

编辑:顺便说一句:提到的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

【问题讨论】:

    标签: python request urllib2 super new-style-class


    【解决方案1】:

    这应该可以正常工作,因为层次结构很简单

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

    【讨论】:

    • 感谢您的回答,但我知道。事实上,我现在正在做这件事。但是,我想在某些方面利用 super() 的强大功能,例如多重继承。
    • 整个层次结构必须是新样式,super 才能正常工作
    • 是的,很遗憾 urllib2 没有使用新式类。我想知道他们为什么这样做
    【解决方案2】:

    使用 super 可能并不总是最佳做法。使用 super 有很多困难。阅读 James Knight 的 http://fuhm.org/super-harmful/ 获取示例。

    该链接显示(以及其他问题)

    1. 超类必须使用 super 如果其子类使用
    2. 所有使用 super 的子类的 __init__ 签名应该匹配。您必须将收到的所有参数传递给超级函数。您的__init__ 必须准备好调用层次结构中任何其他类的__init__ 方法。
    3. 切勿在__init__ 中使用位置参数

    在您的情况下,上述每个标准都被违反。

    詹姆斯奈特也说,

    super() 的唯一情况 实际上会有所帮助的是,当您 拥有钻石传承。乃至 那么,它通常没有那么有用 你可能已经想到了。

    super能正确使用的条件足够繁重,我认为super的用处是相当有限的。更喜欢组合设计模式而不是子类化。如果可以的话,避免钻石继承。如果你从上(对象)到下控制对象层次结构,并且一致地使用超级,那么你就可以了。但由于在这种情况下您无法控制整个类层次结构,我建议您放弃使用super

    【讨论】:

    • 同时,我浏览了右栏中的一些相关问题,也找到了 James Knight 的文章。虽然我仍然认为super() 是一个强大的工具,但我开始了解它的缺点。感谢您详细指出!
    【解决方案3】:

    我认为您错过了将 self 参数传递给示例中 init 的定义。 试试这个:

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

    我测试了它,它似乎工作正常:

    >>> x = ExtendedRequest()
    >>> super(ExtendedRequest, x)
    <super: <class 'ExtendedRequest'>, <ExtendedRequest object>>
    

    【讨论】:

    • 是的,但是当您尝试调用 &lt;super&gt; 对象上的任何方法时,它会引发 AttributeError。
    猜你喜欢
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2015-06-18
    • 1970-01-01
    相关资源
    最近更新 更多