Считается ли дурным тоном создавать исключения внутри __init__
? Если да, то каков принятый метод выдачи ошибки, когда определенные переменные класса инициализируются как None
неправильного типа или имеют неправильный тип?
Считается ли дурным тоном создавать исключения внутри __init__
? Если да, то каков принятый метод выдачи ошибки, когда определенные переменные класса инициализируются как None
неправильного типа или имеют неправильный тип?
Ответы:
Вызов исключений внутри __init__()
- это нормально. Нет другого хорошего способа указать состояние ошибки в конструкторе, и в стандартной библиотеке есть сотни примеров, когда построение объекта может вызвать исключение.
Класс ошибки, который нужно поднять, конечно, зависит от вас. ValueError
лучше всего, если конструктору был передан недопустимый параметр.
ValueError
и TypeError
.
__init__
это не конструктор, а инициализатор. Возможно, вы захотите отредактировать строку. Нет другого хорошего способа указать состояние ошибки в конструкторе ..
Верно, что единственный правильный способ указать ошибку в конструкторе - это вызвать исключение. Вот почему в C ++ и других объектно-ориентированных языках, которые были разработаны с учетом безопасности исключений, деструктор не вызывается, если в конструкторе объекта возникает исключение (что означает, что инициализация объекта не завершена). В языках сценариев, таких как Python, этого часто не происходит. Например, следующий код вызывает ошибку AttributeError в случае сбоя socket.connect ():
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()
Причина в том, что деструктор неполного объекта вызывается после неудачной попытки подключения, до того, как атрибут потока был инициализирован. Не следует избегать генерации исключений из конструкторов, я просто говорю, что на Python сложно написать полностью безопасный код исключений. Некоторые разработчики Python вообще избегают использования деструкторов, но это уже другой спор.
__del__
потому что он плохо написан. У вас была бы точно такая же проблема, если бы вы делали this->p_socket->close()
это в деструкторе на C ++. В C ++ вы бы этого не сделали - вы позволили бы объекту-члену уничтожить себя. Сделайте то же самое в питоне.
Я не вижу причин, по которым это должно быть плохим тоном.
Напротив, одна из вещей, которые, как известно, работают хорошо, в отличие от возврата кодов ошибок, заключается в том, что коды ошибок обычно не могут быть возвращены конструкторами. Так что, по крайней мере, в таких языках, как C ++, создание исключений - единственный способ сигнализировать об ошибках.
Я согласен со всем вышесказанным.
На самом деле нет другого способа сигнализировать о том, что при инициализации объекта что-то пошло не так, кроме как вызвать исключение.
В большинстве программных классов, где состояние класса полностью зависит от входных данных для этого класса, мы можем ожидать возникновения какой-либо ValueError или TypeError.
Классы с побочными эффектами (например, те, которые работают с сетью или графикой) могут вызвать ошибку в init, если (например) сетевое устройство недоступно или объект холста не может быть записан. Мне это кажется разумным, потому что часто вы хотите узнать об условиях отказа как можно скорее.