Измените некоторые элементы коллекции независимо от типа коллекции

#python #collections #iterator

#python #Коллекции #итератор

Вопрос:

Я пытаюсь написать функцию, которая могла бы изменять элементы (типа string) в коллекции любого типа (list, dict и т.д.) Или создает новую коллекцию того же типа с теми же элементами, но измененную в соответствии с моими правилами.

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

Я исправил чувствительный к регистру формат MAC-адресов в MongoDB, например 12:34:56:78:9a:bc . Как мы знаем, 12:34:56:78:9a:bc , 12:34:56:78:9A:BC 12-34-56-78-9A-BC и 123456789abc являются одинаковыми значениями для нас и для физического представления, но они отличаются в MongoDB. Таким образом, моя функция проверит, представляет ли строка MAC-адрес, и преобразует его в требуемый формат. Но я хочу, чтобы он принимал список строк, dict строк в качестве значений, (возможно) кортежи строк, dict списков строк и т.д., Чтобы изменить их значения.

Итак, что у меня есть на данный момент:

 def formMacAddress(addr):
    if type(addr) is str:
        addr = addr.lower()
        if not re.match('[0-9a-f]{2}([-:]?)[0-9a-f]{2}(\1[0-9a-f]{2}){4}$', 
                addr):
            raise ValueError("'{addr}' is not MAC address".format(addr=addr))
        return re.sub('([0-9a-f]{2})[-:]?', 'g<1>:', addr, 5)
    if type(addr) is dict:
        res = {}
        for k, v in addr.items():
            res[k] = formMacAddress(v)
        return res
    if type(addr) is list:
        res = list(addr)
        for k, v in enumerate(addr):
            res[k] = formMacAddress(v)
        return res
    raise ValueError("'{addr}' is not MAC address".format(addr=addr))
  

Итак, проблема в том, что мне не нравятся проверки типов коллекций с одинаковыми телами. В будущем может быть гораздо больше типов. Я ожидал от python возможности избежать этого.

Например, в C я мог бы использовать набор итераторов. В lua может быть только один тип коллекции. Но я не могу найти правильный способ сделать это с помощью python. Я не могу устанавливать значения с помощью итераторов, items() метод не существует в списках и enumerate() применим только к спискам для доступа к их элементам с индексами во время цикла. Чего мне не хватает?

Комментарии:

1. Итак, вы просто хотите повторить общую коллекцию в Python? Разве это не может быть просто сделано в цикле for: for ad in i addr:

2. @running.t, где и как затем поместить измененные ad в новую версию addr коллекции?

Ответ №1:

вы могли бы выполнить итерацию через dict или list или tuple : (вы должны изолировать тип str)

 def formMacAddress(addr):
    seq_iter = addr if isinstance(addr, dict) else range(len(addr))
    print(seq_iter)
    for i in seq_iter:
        print(addr[i])

formMacAddress({"0":"12","1":"34"})
formMacAddress(["0","12"])
formMacAddress(("1","12"))
  

вывод:

 {'0': '12', '1': '34'}
12
34
range(0, 2)
0
12
range(0, 2)
1
12
  

Комментарии:

1. Но могут быть и другие коллекции, кроме dict, доступ к которым осуществляется нечисловыми ключами

2. приведите пример, пожалуйста?

3. Любой пользовательский класс с похожим на dict API, но на основе списка. Например, специальная реализация хэш-таблицы со списком в качестве базового класса и dicts в качестве элементов второго уровня. Скажем, доступ, предоставляемый string, принимая код первого символа в качестве индекса списка первого уровня. Он имеет четко определенный API, похожий на dict, но с собственной дополнительной логикой. В моем случае это точно не появится, но мой вопрос концептуальный. Как избежать любой проверки типа и использовать только общий API? Не предполагая каких-либо различий в типах? Опять же, как в C : просто установите итераторы для любого, даже самого конкретного случая!

4. извините, это мой лучший ответ, единственное, что я мог видеть, это создать свой собственный модуль и импортировать его, а в вашей программе вы выполняете все тесты..