Чи вважається поганою формою збільшення винятків у межах __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, якщо (наприклад) мережевий пристрій недоступний або об'єкт полотна не може бути записаний на нього. Для мене це звучить розумно, тому що часто вам хочеться якомога швидше дізнатися про умови відмови.