W Pythonie często słyszę, że lepiej „błagać o wybaczenie” (wyłapywanie wyjątków) zamiast „pytać o pozwolenie” (sprawdzanie typu / warunku). Jeśli chodzi o wymuszanie pisania kaczek w Pythonie, to jest to
try:
x = foo.bar
except AttributeError:
pass
else:
do(x)
lepszy czy gorszy niż
if hasattr(foo, "bar"):
do(foo.bar)
else:
pass
pod względem wydajności, czytelności, „python” lub innego ważnego czynnika?
exceptions
python
duck-typing
Darkfeline
źródło
źródło
hasattr
jest realizowane wewnętrznie z tą dokładną próbą. Nie jestem pewien, czy to prawda ... (działałoby inaczej na nieruchomościach, prawda? Może myślę ogetattr
...)hasattr
używa C-API równoważnegogetattr
(zwróć,True
jeśli się powiedzie,False
jeśli nie), ale obsługa wyjątków w C jest znacznie szybsza.Odpowiedzi:
To naprawdę zależy od tego, jak często Twoim zdaniem będzie zgłaszany wyjątek.
Oba podejścia są, moim zdaniem, równie ważne, przynajmniej pod względem czytelności i pytoniczności. Ale jeśli 90% twoich obiektów nie ma atrybutu
bar
, zauważysz wyraźną różnicę wydajności między tymi dwoma podejściami:Ale jeśli 90% swoich obiektach nie ma atrybutu, stoły zostały odrzucone:
Dlatego z punktu widzenia wydajności musisz wybrać podejście, które najlepiej pasuje do twoich okoliczności.
Ostatecznie pewne strategiczne użycie
timeit
modułu może być najbardziej pytoniczną rzeczą, jaką możesz zrobić.źródło
hasattr
, że w rzeczywistości robi to w C-api odpowiednik try-poza tym pod maską, ponieważ okazuje się, że jedynym ogólnym sposobem ustalenia, czy obiekt ma atrybut w Pythonie, jest próba dostępu do niego.W Pythonie często osiągasz lepszą wydajność, robiąc rzeczy w taki sposób. W przypadku innych języków stosowanie wyjątków do kontroli przepływu jest ogólnie uważane za okropny pomysł, ponieważ wyjątki zwykle nakładają nadzwyczajne koszty ogólne. Ponieważ jednak ta technika jest wyraźnie zatwierdzona w języku Python, interpreter jest zoptymalizowany dla tego typu kodu.
Podobnie jak w przypadku wszystkich pytań dotyczących wydajności, jedynym sposobem na uzyskanie pewności jest profilowanie kodu. Napisz obie wersje i zobacz, która z nich działa szybciej. Chociaż z mojego doświadczenia wynika, że „sposób w języku Python” jest zazwyczaj najszybszym sposobem.
źródło
Wydaje mi się, że wydajność jest kwestią drugorzędną. Jeśli się pojawi, profiler pomoże ci skupić się na prawdziwych wąskich gardłach, które mogą, ale nie muszą, traktować możliwe nielegalne argumenty.
Z drugiej strony czytelność i prostota zawsze stanowią główny problem. Nie ma tutaj twardych zasad, po prostu skorzystaj z własnego osądu.
Jest to problem uniwersalny, ale istotne są konwencje specyficzne dla środowiska lub języka. Na przykład w Pythonie zazwyczaj wystarczy po prostu użyć oczekiwanego atrybutu i pozwolić potencjalnemu atrybutowi AttributeError dotrzeć do dzwoniącego.
źródło
Jeśli chodzi o poprawność , myślę, że rozwiązaniem jest obsługa wyjątków (czasem jednak sam używam metody hasattr ()). Podstawowym problemem związanym z poleganiem na hasattr () jest to, że zamienia naruszenia kontraktów w cichą awarię (jest to duży problem w JavaScript, który nie rzuca nieistniejących właściwości).
źródło