Лучший способ написать для цикла при возможности доступа к элементам в контейнере Python

1

Это относительно простой, но более острый вопрос о том, как писать наиболее сжатый цикл if/any/for, который выполняет то, что мне нужно. Я новичок в Python и гораздо больше привык к работе C++.

Мне нужно сделать что-то вроде следующего:

for item in my_dict:
    if some_var == item.some_attribute:
        if item.another_attribute exists:
            variable = "A"
        else variable = "B"
        print "Duplicate item exists in my list of type: {}".format(variable)

Я сконцентрировал это на чем-то вроде этого:

if any(some_var == item.some_attribute for item in my_dict):
    variable = "A" if item.another_attribute else "B"
    print "Duplicate item exists in my list of type: {}".format(variable)

Однако при этом я получаю ошибку "неразрешенной ссылки" для item. Любые идеи относительно того, как я могу написать сжатый цикл, проверку эквивалентности и проверку присутствия, как я описал выше, таким образом, что позволяет мне получать доступ и выполнять методы по item?

Спасибо!

EDIT: Большое вам спасибо за ответ @pjhaugh, что именно то, что я искал. Прекрасно работает! Спасибо всем за ваши полезные комментарии.

Теги:
loops

3 ответа

0
Лучший ответ

Что здесь происходит, так это то, что item не течет из области выражения генератора (это хорошо). Вы можете получить item, получив следующее, полученное генератором, или поймав этот генератор, ничего не давая.

try:
    item = next(item for item in my_dict if some_var == item.some_attribute)
    variable = "A" if item.another_attribute else "B"
except StopIteration:
    # there is no such item in my_dict
0

Как указано в моем комментарии - any(some_var == item.some_attribute for item in my_dict) создает свою собственную локальную область. Вы не можете использовать item за его пределами.

Тем не менее, вы можете запрограммировать свой dict так:

Создайте минимальные проверяемые полные данные примера:

class K:
    def __init__(self):
        self.some_attribute = None
        self.another_attribute = None

    def __repr__(self):
        return "{}  - {}".format(self.some_attribute,self.another_attribute)
    def __str__(self):
        return "{}  - {}".format(self.some_attribute,self.another_attribute)

k1 = K()
k1.some_attribute = 99
k2 = K()
k2.some_attribute = 33
k3 = K()
k3.some_attribute = 33
k3.another_attribute = 1

my_dict = { 1: k1, 2:k2, 3:k3}
some_var = 33

Вы можете использовать цикл for так:

variable = None
for item in my_dict.items():
    k,v = item
    if v.some_attribute != some_var:
        print "No dupe: {}".format(v)
        continue
    if v.some_attribute == some_var and v.another_attribute is not None:
        variable = "A"
    else: 
        variable = "B"
    print "Duplicate item exists in my list of type: {}".format(variable)
    print v

Выход:

No dupe: 99  - None
Duplicate item exists in my list of type: B
33  - None
Duplicate item exists in my list of type: A
33  - 1
0

Вы можете извлечь объекты, предоставленные итератором, в цикле for, подобном этому

   for item in (i for i in my_dict if some_var == item.some_attribute):
        variable = "A" if item.another_attribute is not None else "B"
        print("Duplicate item exists in my list of type: {}".format(variable))
        break
   else:  # no break encountered
       ...  # not found

В настоящее время вы повторяете ключи словаря. Если вам нужны элементы (пары в c++ lingo), вам нужно my_dict.items().

Ещё вопросы

Сообщество Overcoder
Наверх
Меню