Я использую модуль Python unittest
и хочу проверить, равны ли две сложные структуры данных. Объектами могут быть списки dicts со всеми значениями: номерами, строками, контейнерами Python (списки/кортежи/dicts) и numpy
массивами. Последние являются причиной задавать вопрос, потому что я не могу просто сделать
self.assertEqual(big_struct1, big_struct2)
поскольку он создает
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
Я предполагаю, что для этого мне нужно написать свой собственный тест на равенство. Он должен работать для произвольных структур. Моя текущая идея - это рекурсивная функция, которая:
- пытается прямое сравнение текущего "node"
arg1
с соответствующим node ofarg2
; - Если исключение не создано, он перемещается (здесь также обрабатываются "конечные" узлы/листья);
- если
ValueError
пойман, идет глубже, пока не найдетnumpy.array
; - сравнивает массивы (например, как это).
Кажется, что проблематично отслеживать "соответствующие" узлы двух структур, но, возможно, zip
- это все, что мне нужно.
Вопрос: есть ли хорошие (более простые) альтернативы этому подходу? Может быть, numpy
содержит некоторые инструменты для этого? Если альтернативы не предложены, я реализую эту идею (если у меня не будет лучшей) и опубликую ответ.
P.S. У меня есть смутное чувство, что я мог бы рассмотреть вопрос, касающийся этой проблемы, но я не могу найти его сейчас.
P.P.S. Альтернативный подход - это функция, которая пересекает структуру и преобразует все numpy.array
в списки, но проще ли это реализовать? Кажется таким же для меня.
Изменить: Подклассификация numpy.ndarray
звучит очень многообещающе, но, очевидно, у меня нет двух сторон сравнения, жестко закодированных в тесте. Один из них, правда, действительно жестко закодирован, поэтому я могу:
- заполнить его пользовательскими подклассами
numpy.array
; - измените
isinstance(other, SaneEqualityArray)
наisinstance(other, np.ndarray)
в jterrace ответ; - всегда используйте его как LHS в сравнении.
Мои вопросы в этом отношении:
- Будет ли это работать (я имею в виду, это звучит для меня правильно, но, может быть, некоторые сложные случаи кросс не будут обрабатываться правильно)? Будет ли мой пользовательский объект всегда заканчиваться как LHS в рекурсивных проверках равенства, как я ожидаю?
- Опять же, есть ли лучшие способы (учитывая, что я получаю хотя бы одну из структур с реальными массивами
numpy
).
Изменить 2. Я пробовал это, рабочая версия (по-видимому) показана в этом ответе.