Używam modułu Pythona unittest
i chcę sprawdzić, czy dwie złożone struktury danych są równe. Obiekty mogą być listami dyktów z różnymi rodzajami wartości: liczbami, łańcuchami znaków, kontenerami w języku Python (listy/krotki/znaki) i tablicami numpy
. Te ostatnie są powodem zadać pytanie, bo nie można po prostu zrobićPorównać (potwierdzić równość) dwie złożone struktury danych zawierające numpy tablice w unittest
self.assertEqual(big_struct1, big_struct2)
ponieważ wytwarza
ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
Wyobrażam sobie, że muszę napisać własny testu równości dla tego produktu. Powinno działać dla dowolnych struktur. Mój obecny pomysł jest rekurencyjna funkcja:
- próbuje bezpośrednie porównanie obecnego „węzła” w
arg1
do analogicznego węzłaarg2
; - jeśli nie ma wyjątków, porusza się (tutaj przetwarzane są także "końcowe" węzły/liście);
- jeśli zostanie przechwycony
ValueError
, będzie głębiej, dopóki nie znajdzienumpy.array
; - porównuje tablice (np. like this).
To, co wydaje się trochę problematyczne, to śledzenie "odpowiadających" węzłów dwóch struktur, ale być może potrzebne jest tutaj tylko zip
.
Pytanie brzmi: czy istnieją dobre (prostsze) alternatywy dla tego podejścia? Może numpy
przedstawia kilka narzędzi do tego? Jeśli nie zostaną zaproponowane żadne alternatywy, zaimplementuję ten pomysł (chyba że mam lepszy) i opublikuję jako odpowiedź.
P.S. Mam niejasne przekonanie, że mogłem zobaczyć pytanie dotyczące tego problemu, ale nie mogę go teraz znaleźć.
P.P.S. Alternatywnym podejściem byłoby funkcja przechodząca przez strukturę i przekształcająca wszystkie listy, ale czy jest to łatwiejsze do wdrożenia? Wydaje mi się to samo.
Edit: Utworzenie podklasy numpy.ndarray
brzmi bardzo obiecująco, ale oczywiście nie mam obie strony stosunku zakodowane w teście. Jednak jeden z nich jest rzeczywiście zakodowany, więc mogę:
- zapełnić go niestandardowymi podklasami
numpy.array
; - zmiana
isinstance(other, SaneEqualityArray)
naisinstance(other, np.ndarray)
w jterrace's answer; - zawsze używaj go jako LHS w porównaniach.
Moje pytania w tym zakresie są:
- będzie działać (mam na myśli, to brzmi dobrze dla mnie, ale może jakieś skomplikowane przypadki brzegowe nie będą obsługiwane poprawnie)? Czy mój niestandardowy obiekt zawsze kończy się jako LHS w rekurencyjnych sprawdzaniach równości, jak się spodziewam?
- Ponownie, czy istnieją lepsze sposoby (biorąc pod uwagę, że otrzymuję co najmniej jedną strukturę z prawdziwymi tablicami
numpy
).
Edycja 2: próbowałem go, realizacja (pozornie) pracy jest pokazany na this answer.
Wyobrażam sobie, że pisanie testu równości, który działa na dowolnych struktur danych byłoby dowolnie trudne. Czy naprawdę nie ma dla nich stałej struktury? – goncalopp
@ Gonkalopp Jest ich kilka, dość zawiłych i teoretycznie podlegają zmianom. Nie chcę na tym polegać, zwłaszcza, że nie znam sposobu porównywania wszystkiego z wyjątkiem 'X'_ w dwóch strukturach, nawet jeśli wiem, gdzie jest' X'. –
Następnie, osobiście, zastosowałem podejście funkcji rekursywnej. Najpierw jednak dokładnie sprawdziłbym typ obiektu - wykonanie ślepego porównania jako pierwszego kroku może być dobre, ale byłoby marnotrawstwem, gdyby struktury danych były duże, ponieważ wartości będą musiały zostać ponownie sprawdzone, jeśli: ValueError' jest podniesiony. – goncalopp