Перебор перечисления IntFlag с использованием iter отличается в Python 3.8 и 3.12.4

У меня в Python 3.8.1 работает следующее:

@unique
class Encoder(IntFlag):
    # H1 sensor signal
    H1 = 0x00
    # H2 sensor signal
    H2 = 0x01
    # H3 sensor signal
    H3 = 0x02

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

from enum import unique, IntFlag
signal = Encoder.H1
assert signal in iter(Encoder), f"Valid Encoder line is integer 0 to 2 inclusive."

Я заметил, что в Python 3.8 сигнал в iter (Encoder) возвращает True, но False в Python 3.12.4.

Это может быть изменение в какой-то версии с 3.8.1 на 3.12.4, но я не уверен, с чего начать, чтобы это работало в обеих.

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

enum.Flag реализует __содержит__.

Чтобы проверить членство, позвоните iter и просто используйте:

signal in Encoder

Это будет работать как в 3.8.1, так и в 3.12.4.

Примечание. Изменение поведения итерации флагов произошло в Python 3.11 и упоминается в журнале изменений здесь.

Кроме того, вам, вероятно, все равно следует использовать IntEnum, а не IntFlag. IntFlag было бы уместно в случае использования, где Encoder.H2 | Encoder.H3 имело значение и означало «оба из них». В вашем случае Encoder.H2 | Encoder.H3 — недопустимое значение.

Изменение поведения итерации напрямую не упоминается в журнале изменений. Скорее, H1 больше не считается канонической формой. Вместо этого он считается псевдонимом чего-то вроде H2 & H3.

Dunes 27.06.2024 17:54

@Dunes Это комбинация этого и добавления Flag.__iter__. Последний и предпоследний пункты в моей ссылке. Не знаю, как Итану удалось это изменить без периода устаревания, но мне это кажется обратным изменением.

wim 27.06.2024 18:01

Связано: github.com/python/cpython/issues/109633

wim 27.06.2024 18:56

Мне интересно, есть ли здесь регресс. Например, H0 считается членом перечисления и продолжает существовать как атрибут перечисления. Однако dir(Encoder) больше не возвращает его имя. Это противоречит документации __dir__, в которой говорится, что она возвращает всех членов — как канонических, так и псевдонимов.

Dunes 27.06.2024 20:45

Также стоит отметить, что __contains__ также возвращает true для любого значения составного флага, а не только для именованных флагов. например. assert (H2 | H3) in Encoder, но assert (H2 | H3) not in Encoder.__members__

Dunes 27.06.2024 20:55

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