Python: поменять позицию расширения vars

Моя функция получает объект myenum, который может быть set или dict.
{'a', 'b', 'c'}
или
{'a': 5, 'b' : 2, 'c' : 8}

Он представляет перечисление, как в C/C++.

В случае dict мне нужно перечислить .items() в случае set мне нужно использовать enumerate(myenum) вот так

for k, i in myenum.items():

for i, k in enumerate(myenum):

Я мог бы использовать тройную систему itr = myenum.items() if hasattr(myenum, 'keys') else enumerate(myenum) А потом просто иметь сингл for.

К сожалению, .items() расширяется до key, value, а enumerate() расширяется до index, key. index на самом деле является желаемым значением перечисления.

Есть ли возможность поменяться местами в дополнении? Значит, enumerate() тоже превращается в key, index?

Прямо сейчас у меня есть наивное решение из двух одинаковых циклов for, только порядок k, i разный, что некрасиво.

Не проверяйте, принадлежит ли объект заданному типу с помощью hasattr, вместо этого используйте isinstance.

matszwecja 15.04.2024 15:24

Используете ли вы значения в цикле for в случае dict? Было бы полезно, если бы вы показали больше кода в циклах.

Jab 15.04.2024 15:24

Это тот случай, когда вызывающая сторона, а не ваша функция, должна нести ответственность за создание соответствующего значения Iterable[str, int] из любого имеющегося у них набора, словаря и т. д.

chepner 15.04.2024 15:35

@matszwecja Python — это язык утиного набора текста, существует бесконечное количество тем, доказывающих, что использование isinstance — худший подход. Если объект является итеративным и имеет ключи - для меня это так, даже если он не является производным от dict. Завтра эта функция тоже получит dict и ваш код сломается, а мой все еще будет в порядке

Noob 15.04.2024 16:19
Почему в 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
4
63
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете заархивировать set с помощью range и преобразовать его в dict.

def func(myenum):
    if isinstance(myenum, set):
        myenum = dict(zip(myenum, range(len(myenum))))

    for k, i in myenum.items():
        print(k, i)

Должен признать, это элегантная альтернатива моей проблеме и она мне нравится. К сожалению, другой ответ от fsimonjetz больше соответствует теме вопроса, поэтому пришлось принять его. Тем не менее, большое спасибо! Однако одно замечание. Поскольку Python использует утиный ввод, проверка на isinstance менее выгодна. Но это незначительно

Noob 15.04.2024 16:12
Ответ принят как подходящий

Есть ли возможность поменяться местами в дополнении? Итак, enumerate() также расширяется до ключа и индекса?

Если вам нужно только поменять их местами, это должно вести себя точно так же, как enumerate, за исключением замененных элементов.

def swap_enumerate(enum):
    return ((k, i) for i, k in enumerate(enum))

Хотя мне больше нравится решение @Guy, но оно отвечает именно на мой вопрос, поэтому я принимаю его. Спасибо!

Noob 15.04.2024 16:08

Я бы исправил set в dict, если это применимо. Тогда я бы имел дело только с dict.

def f( myenum ):
    if isinstance(myenum, set):
        myenum = { v : k for k, v in enumerate(myenum) }
    
    for key, value in myenum.items():
        ...

Разложите свою функцию на две более простые функции: одна преобразует набор или словарь в соответствующую итерацию, а другая использует итерацию.

from typing import Iterable, TypeVar

K = TypeVar('K')

def convert(c: dict[K, int] | set[K]) -> Iterable[tuple[K, int]]:
    if isinstance(c, dict):
        return c.items()
    else:
        return ((k, i) for i, k in enumerate(c))

def process(pairs: Iterable[K, int]):
    for k, i in pairs:
        ...

def func(c: dict[K, int] | set[K]):
    process(convert(c))

Вы можете рассмотреть возможность реализации только process и оставить convert для реализации тому, кто хочет использовать process.

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