#python #urllib #namedtuple
#python #urllib #namedtuple
Вопрос:
Я пытаюсь ввести базовую аутентификацию в URL-адрес с помощью split-inject-join:
url = urllib.parse.urlsplit(url)
new_url = url._replace(username=user, password=password)
Но я удивлен поведением SplitResult
, которое я получаю от urllib.parse.urlsplit
метода:
>>> 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']
Кажется, что None
поля в этом SplitResult
не могут быть заменены. Это странно, поскольку в документации утверждается, что это именованный кортеж.
Когда я делаю эквивалент с помощью самостоятельно созданного именованного кортежа, оказывается, что поля ‘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
, что отличает?
Ответ №1:
В документации не указаны индексы для полей username
, password
, hostname
, или port
. Это говорит о том, что они на самом деле не являются частью namedtuple , а вместо этого являются просто атрибутами SplitResult
объекта. Глядя на реализацию CPython, кажется SplitResult
, что она наследуется как от namedtuple, содержащего первые несколько полей с индексами, так и от mixin, который добавляет другие поля в качестве свойств.