UrlSplitResult:无法_replace 字段

UrlSplitResult: can't _replace fields

我正在尝试通过 split-inject-join 将基本身份验证注入 url:

    url = urllib.parse.urlsplit(url)
    new_url = url._replace(username=user, password=password)

但是我对从 urllib.parse.urlsplit 方法得到的 SplitResult 的行为感到惊讶:

>>> v = urlsplit('http://a.b/c/d')
>>> v.username is None and v.password is None  # None, but accessible
True
>>> v._replace(scheme='ftp')  # beautiful!  Just like expected.
SplitResult(scheme='ftp', netloc='a.b', path='/c/d', query='', fragment='')

# however...
>>> v._replace(scheme='ftp', username='u', password='p')
...ValueError: Got unexpected field names: ['username', 'password']

这个SplitResult中的None字段好像不能替换。这很奇怪,因为 the documentation 声称它是 命名元组。

当我用一个自建的命名元组做同样的事情时,'None' 字段 可以 毫无问题地被替换。

>>> T = namedtuple("T", ("a", "b", "c"))
>>> t = T(a=1, b=2, c=None)
>>> t
T(a=1, b=2, c=None)
>>> t._replace(c=3)
T(a=1, b=2, c=3)

但是替换不存在的字段也会触发同样的异常。

>>> t._replace(d=4)  # should raise, please
...ValueError: Got unexpected field names: ['d']
# I was expecting an AttributeError, but hey...

然而,在这种情况下,意外的字段确实无法访问:

>>> t.d is None
...AttributeError: 'T' object has no attribute 'd'

知道 SplitResult 的不同之处吗?

文档未列出字段 usernamepasswordhostnameport 的索引。这表明它们实际上并不是 namedtuple 的一部分,而只是 SplitResult 对象的属性。查看 CPython implementation, it seems like SplitResult inherits from both the namedtuple containing the first few fields which have indices, as well as a mixin which adds the other fields as properties.