Я встречал странное поведение Python, которое трудно объяснить самому себе. Когда я передаю значение по умолчанию для получения ключа из словаря, похоже, сначала он пытается найти это значение по умолчанию, а затем проверяет, существует ли ключ. И выдает ошибку, если ключ существует в dict. Почему это происходит?
from collections import namedtuple
Test = namedtuple("TEST", "attr1 attr2 attr3")
obj_1 = Test("first", "second", "third")
obj_1.attr1
>>> 'first'
k_dict = {"red": "light", "green": "leaf"}
k_dict.get("red")
>>> 'light'
k_dict.get("red", obj_1.attr4)
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'TEST' object has no attribute 'attr4'
Обновлено: Я понимаю, в чем здесь проблема, но я не могу понять, почему это поведение Python по умолчанию? Почему бы просто не проверить первую часть - есть ли key
в dict, а если нет - проверить другую часть? Теперь это выглядит не оптимальным способом вычисления?
attr4
не является частью вашего namedtuple, он идет только до attr3
@freakish именно об этом я и спрашиваю - почему python проверяет, существует ли атрибут, прежде чем искать, присутствует ли ключ в dict?
Это не .get()
, это потому, что вы пытаетесь использовать что-то attr4
, которого не существует. Ответ Джин объясняет это лучше.
@ Джошуа Никсон Я понимаю это, но я не называю это значение напрямую. На мой взгляд, это следует вызывать необязательно, если ключ отсутствует в dict. Но почему Python проверяет это раньше? Почему бы не проверить, существует ли ключ, а затем проверить, существует ли attr4
?
Python проверяет значение при передаче его методу. Python или любой другой язык не может передать в метод то, чего не существует.
это не имеет ничего общего с dict.get
Когда вы вызываете функцию в python, аргументы оцениваются.
В вашем случае ключ существует, но перед поиском ключа необходимо оценить оба аргумента.
Например, что будет «работать»:
k_dict.get("red") or obj_1.attr4
Поскольку ключ red
существует, второй аргумент не оценивается. Он падает только в том случае, если red
не существует. В этом случае это не очень помогает (ваш способ сделать это имеет право на обнаружение ошибки независимо от результата, по крайней мере, так что продолжайте делать это!), но если у вас есть какие-то сложные вычисления для выполнения в качестве аргумента по умолчанию, это было бы:
k_dict.get("red",super_expensive_computation())
работает медленно, даже если red
существует, когда:
k_dict.get("red") or super_expensive_computation()
работает быстро, когда существует red
. Техника or
основана на том факте, что значения не могут быть 0
, а только None
. В противном случае просто используйте конструкцию if "red" in k_dict
.
Я смущен. Вы делаете
obj_1.attr4
, а наattr4
нетobj_1
. Что именно вы здесь не понимаете?