return Tuple or Dict?

0

Cześć, uczę się programowania w pythonie dopiero i powiedzcie mi prosze jak podejść do mojego problemu prawidłowo.

Mam taką sytuację iż wywołuje pewną metodę najlepiej pokażę to na assercie

check_result = foo() # przykład do zobrazowania
assert check_result['status'], str('[Some Block] Api should return x for ...... . Validation message %s' % check_result['message'])
dynamic_dict[some_value] = check_result['searched_value']

Chodzi o to, że wywołuje sobie jakąś metodę. Zadaniem metody jest zwócenie szukanych informacji ale też posiada wewnętrzny validator i status pomyślności wykonania zadania.
I teraz pytanie jest takie czy bazująć na słowniku nie łamie jakiś konwencji pythonowych?? Wiem że istnieje możliwość tupla, ale nie podoba mi się z tego wzgledu iż moja funkcja ma trchę nagnierzdzeń gdzie wrzucam słownik i jest zwracanyz uzupełnieniem poszczególnych parametrówl.

0

Jesli dobrze zrozumialem twoja metoda/funkcja foo() zwraca slownik.
Ogolnie samo zwracanie slownika przez metode jest OK.

Inne typy sa rowniez OK ale wszystko zalezy od dokladnego kontekstu.

Zadnych konwencji nie lamiesz.

0

To może kontekts przykładowego zagnieżdrzenia funkcji foo(). Każde zangdzieżdrzenie posiada innego messaga w dict, żebym mógł w jednym miejscu po wywołaniu foo zweryfikować co poszło nie tak. Logi to dla mnie podstawa ;)
I w zależnosći od założenia funkcji foo czyli jej statusu, albo podejmuje dalsze działania jak jest False albo jak Jest True. Pod dalszymi działaniami chodzi mi o to że doklejam niezbędne zmienne do słownika. Tutaj daje przykład dla jakiegoś foo gdzie podejmuje dalsze działania jak status jest False. Np zapisanie obrazków ;)) (Wszystkie pod funkcje kierują się tym samym założeniem)

    def _compare_image_regression(self, orginal_img, compare_img):
        result = {
            'status': True,
            'message': 'ok',
        }

        img_orginal_gray = cv2.cvtColor(orginal_img, cv2.COLOR_BGR2GRAY)
        img_compare_gray = cv2.cvtColor(compare_img, cv2.COLOR_BGR2GRAY)

        score, diff = self._compare_image_ssim(img_orginal_gray, img_compare_gray)

        if score != 1:
            thresh, cnts = self._get_tresh_and_cnts(diff)

            images = {
                'orginal' : orginal_img
                ,'compared' : compare_img
                ,'orginal_marked' : self._get_image_with_rectangle(cnts, orginal_img)
                , 'compared_marked' : self._get_image_with_rectangle(cnts, compare_img)

            }

            result['status'] = False
            result['message'] = 'Check Image'
            result['images'] = images

        return result

Pytanko czy jest to ok dla Pythona, wcześniej głownie backend to pisałem w .Net / node.js / Java / Apex. Niestety muszę teraz dużo robić w pythonie bo ma lepsze biblioteki ^^ które można z sobą fajnie połaczyć ;)

BTW, był bym dzięczny za linka do jakiejś skróconej wersji dobrych praktyk do pythona bo nie mam na to czasu by czytać jakieś duże wypracowania. Wiem jestem leniem (BTW Każdy programista jest leniem, jak kożysta z czyiś blibliotek ;P). Dzieki z góry!!!!

0

Dobrą praktyką byłoby podnieść wyjątek i nie zwracać już wartości logicznej opisującej powodzenie.

0

Zgadzam się ale ;) nie jestem zwolenikiem wyjatków a nawet przeciwnikiem, zwłaszcza jak mówimy o bibliotekach pod testy automatyczne.

Dla czego??
Po pierwsze w testach automatycznych rozrózniamy 3 typy stanu powodzenia tesótw:
Zielony: Pass testy przeszły
Czerwony: Fail testy nie przeszły. Coś się nie zgadza.
Żółty: Error code - Ktoś coś zmaścił, brakuje jakiś plików do testów, wysypała się jakaś blilioteka, system nie działą poprawnie, brak połaczenia z internetem w skrócie stało się coś nie przewidzianego.

I tylko dla Code error są przewidziane wyjątki, i wtedy postrzegamy testy inaczej.

Jak ja bym chciał obsługiwać bibliotekę pod testy automatyczne obługiwać wyjątkami, to zamiast asertów bym musiał robić tbloki try catch i róznego rodzaju exceptiony obsługiwać.
Przypominam, że jak jest fail testu np ja muszę zapisać zdjęcia odpowienio. Try mi tego nie obsłuży.

Dla tego ten pomysł pod to odpada. Ale tak ogólnie zgadzam się, jak piszemy aplikacje czy jakieś specyficzne bliblioteki np prównujące 2 pliki i coś tam pierdzielnie to walimy wyjątek. Gożej jak musimy taki przypadek jakoś obsłużyć na zasadzie rosrzerzyć zdjecie itp.

0

A ja właśnie w ostatnim projekcie (testy automatyczne) przerobiłem masę skryptów typu if fail: return False na rzucanie wyjątkami. Python lubi wyjątki :) Jest wydajniej ale co najważniejsze łatwiej zwolnić zasoby. Jeżeli Twoja biblioteka testująca np. nawiązuje połączenie z urządzeniem embedded, tworzy jakieś zasoby, inicjalizuje pewne stany w urządzeniach fizycznych warto zastosować context handlery, które te zasoby zwolnią w razie wyjątków. I kod napisany z obsługą wyjątków jest o wiele bardziej czytelny i w przypadku skomplikowanych projektów szybciej zauważysz gdzie leży problem jak np. dostaniesz wyjątek ParseErrorInFnX niż kod zwróci Ci "False" i szukaj w logach i debuguj po kolei.

Aale powiedziawszy to oczywiście Twój wypadek jest przypadkiem specyficznym i trudno tu dać wyjątek. Gdy patrzę na tą funkcję myślę, że można jednak to rozbić dla jasności. Funkcja compare_image_regression powinna zwrócić score, diff (bo przecież ona tylko robi "compare regression" a nie "compare regression and return result frame") i poza nią już sprawdzić score w innej funkcji np. def isSimiliar(score): return score==1 i odpowiednio spreparować result.

I zwracać coś w stylu True/False, optional_result_value i potem

ret, *retDict = your_function()
if not ret:
   #do something with retDict

0

Scora i diff zwraca compare_regression_simm xd i ona w razie czego rzuca wyjatkiem. Wyjatki lapie na poziomie klasy testujacej w funkcjach setup test thearddown i tylko na tym poziomie obsluguje.

Ale dzieki za ten przyklad. Jakbys umial wrzucic taki pelny przyklad az pod asserta byl bym wdzieczny. Moze bym lepiej zrozumial.

0

Jakby cos to jest jedno z 4 odbic glownej foo. Moze zle ja nazwalem ale zadaniem tej funckji jest sprawdzenie czy na obrazku o tych samych szerokosciach sa roznice a jak tak to zwrocenie obrazkow z ramkami. Hmm chyba masz racje sprawdzic czy sa roznice i nowa funckje co zajmie sie zwroceniem obrysowanych i potem zapis. Ladniej to bedzie wygladac. I mozna by bylo twoja konwencje zastosowac.

0
młody kot napisał(a):

Zgadzam się ale ;) nie jestem zwolenikiem wyjatków a nawet przeciwnikiem, zwłaszcza jak mówimy o bibliotekach pod testy automatyczne.

W Pythonie zalecana jest zasada EAFP (easier to ask for forgiveness than permission) -- co się sprowadza do założenia, że wszystko jest OK, a jak nie to wyskakuje wyjątek.

Ponadto, w Pythonie wyjątki są wydajne (w porównaniu z resztą języka) i wygodne.

0

OK jak już na spokojnie spojrzałem to masz taką opcję też:

class YourError(Exception):
    def __init__(self, message, images):
        self.message = message
        self.images = images

try:
    images = {key: value}
    raise YourError("some error msg", images)
catch YourError as e:
    print(e.images)

Zachowujesz plusy korzystania z wyjątków i możesz przekazać wartości do dalszej analizy. Możesz nawet zrobić:

class YourError(Exception):
     pass

try:
    raise YourError({key: value})
except YourError as e:
    result = e.args[0]
    print(result['key'])

Ale lepiej już napisać klasę jak w przykładzie na początku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1