Czy zgłaszanie wyjątków w ramach programu jest złą formą __init__
? Jeśli tak, to jaka jest akceptowana metoda zgłaszania błędu, gdy pewne zmienne klasy są inicjowane jako None
lub niepoprawnego typu?
Czy zgłaszanie wyjątków w ramach programu jest złą formą __init__
? Jeśli tak, to jaka jest akceptowana metoda zgłaszania błędu, gdy pewne zmienne klasy są inicjowane jako None
lub niepoprawnego typu?
Odpowiedzi:
Zgłaszanie wyjątków w ramach __init__()
jest absolutnie w porządku. Nie ma innego dobrego sposobu na wskazanie warunku błędu w konstruktorze, aw bibliotece standardowej istnieje wiele setek przykładów, w których zbudowanie obiektu może zgłosić wyjątek.
Klasa błędu, którą należy podnieść, zależy oczywiście od Ciebie. ValueError
najlepiej, jeśli do konstruktora przekazano nieprawidłowy parametr.
ValueError
i TypeError
.
__init__
Zwracam tylko uwagę, że nie jest konstruktorem, tylko inicjatorem. Możesz chcieć edytować linię Nie ma innego dobrego sposobu na wskazanie stanu błędu w konstruktorze, ...
Prawdą jest, że jedynym właściwym sposobem wskazania błędu w konstruktorze jest zgłoszenie wyjątku. Dlatego w C ++ i innych językach obiektowych, które zostały zaprojektowane z myślą o bezpieczeństwie wyjątków, destruktor nie jest wywoływany, jeśli w konstruktorze obiektu zostanie zgłoszony wyjątek (co oznacza, że inicjalizacja obiektu jest niekompletna). Często tak nie jest w językach skryptowych, takich jak Python. Na przykład poniższy kod zgłasza błąd AttributeError, jeśli funkcja socket.connect () nie powiedzie się:
class NetworkInterface:
def __init__(self, address)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect(address)
self.stream = self.socket.makefile()
def __del__(self)
self.stream.close()
self.socket.close()
Przyczyną jest to, że destruktor niekompletnego obiektu jest wywoływany po nieudanej próbie połączenia, przed zainicjowaniem atrybutu strumienia. Nie należy unikać wyrzucania wyjątków z konstruktorów, mówię tylko, że trudno jest napisać w Pythonie kod w pełni bezpieczny dla wyjątków. Niektórzy programiści Pythona całkowicie unikają używania destruktorów, ale to już kwestia innej debaty.
__del__
ponieważ jest źle napisany. Miałbyś dokładnie ten sam problem, gdybyś zrobił this->p_socket->close()
w destruktorze w C ++. W C ++ nie zrobiłbyś tego - pozwoliłbyś obiektowi składowemu sam się zniszczyć. Zrób to samo w Pythonie.
Nie widzę powodu, dla którego miałaby to być zła forma.
Wręcz przeciwnie, jednym z wyjątków, które są znane z tego, że radzą sobie dobrze, w przeciwieństwie do zwracania kodów błędów, jest to, że konstruktorzy zwykle nie mogą zwracać kodów błędów . Tak więc przynajmniej w językach takich jak C ++ zgłaszanie wyjątków jest jedynym sposobem sygnalizowania błędów.
Zgadzam się z powyższym.
Tak naprawdę nie ma innego sposobu, aby zasygnalizować, że coś poszło nie tak podczas inicjalizacji obiektu, niż zgłoszenie wyjątku.
W większości klas programów, w których stan klasy jest całkowicie zależny od danych wejściowych tej klasy, możemy spodziewać się podniesienia pewnego rodzaju wartości ValueError lub TypeError.
Klasy z efektami ubocznymi (np. Takie, które obsługują sieć lub grafikę) mogą powodować błąd w init, jeśli (na przykład) urządzenie sieciowe jest niedostępne lub nie można zapisać do obiektu kanwy. Wydaje mi się to rozsądne, ponieważ często chcesz wiedzieć jak najszybciej o warunkach awarii.