Как метод Python dict .get() проверяет аргумент по умолчанию?

Я встречал странное поведение 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, а если нет - проверить другую часть? Теперь это выглядит не оптимальным способом вычисления?

Я смущен. Вы делаете obj_1.attr4, а на attr4 нет obj_1. Что именно вы здесь не понимаете?

freakish 23.01.2019 16:01
attr4 не является частью вашего namedtuple, он идет только до attr3
Joshua Nixon 23.01.2019 16:01

@freakish именно об этом я и спрашиваю - почему python проверяет, существует ли атрибут, прежде чем искать, присутствует ли ключ в dict?

Chiefir 23.01.2019 16:02

Это не .get(), это потому, что вы пытаетесь использовать что-то attr4, которого не существует. Ответ Джин объясняет это лучше.

Joshua Nixon 23.01.2019 16:02

@ Джошуа Никсон Я понимаю это, но я не называю это значение напрямую. На мой взгляд, это следует вызывать необязательно, если ключ отсутствует в dict. Но почему Python проверяет это раньше? Почему бы не проверить, существует ли ключ, а затем проверить, существует ли attr4?

Chiefir 23.01.2019 16:05

Python проверяет значение при передаче его методу. Python или любой другой язык не может передать в метод то, чего не существует.

Joshua Nixon 23.01.2019 16:11
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
131
1

Ответы 1

это не имеет ничего общего с 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.

Другие вопросы по теме