Чому повертати NotImplemented замість підвищення NotImplementedError


281

У Python є сінгтон, який називається NotImplemented.

Чому хтось хотів би коли-небудь повернутися NotImplementedзамість того, щоб підняти NotImplementedErrorвиняток? Чи не буде просто важче знайти помилки, наприклад, код, який виконує недійсні методи?

Відповіді:


280

Це тому, що __lt__()і споріднені методи порівняння досить часто опосередковано використовуються в списках сортів і подібних. Іноді алгоритм вирішить спробувати інший спосіб або вибрати переможця за замовчуванням. Підвищення винятку вирветься із роду, якщо не буде спіймано, тоді як NotImplementedне піднімається і може бути використане в подальших тестах.

http://jcalderone.livejournal.com/32837.html

Щоб узагальнити це посилання:

" NotImplementedсигналізує під час виконання, що він повинен попросити когось іншого задовольнити операцію. У виразі a == b, якщо a.__eq__(b)повертається NotImplemented, тоді Python намагається b.__eq__(a). Якщо bзнає достатньо, щоб повернутися Trueабо False, тоді вираз може досягти успіху. Якщо це не відбудеться, тоді виконання буде повернутися до вбудованої поведінки (яка заснована на ідентичності для ==та !=) ".


5
Я був би обережний, використовуючи його, оскільки це посилання вказує наприкінці документа.
Джейсон Кун

16
Коли інтерпретатор Python перевіряє, чи a.__eq__(b)повертається NotImplemented, чи не міг він так само легко спіймати NotImplementedError замість цього (і дзвонити b.__eq__(a)чи що далі)?
Векі

24
@Veky. Підвищення винятку, ймовірно, має більші витрати. Будь-які накладні витрати в операції сортування збільшуватимуться за розміром списку, тому навіть якщо різниця була дуже невеликою, все одно має сенс знайти більш швидку реалізацію. Ви також не хочете виривати свої петлі та повторно вводити їх, що вимагатиме впровадження спробувати.
SpliFF

3
По-перше, ще більш швидким рішенням було б автоматично синтезувати lt як зворотний gt, а не завжди викликати щось, що поверне NotImplemented - і Python цього не зробить. Я не думаю, що швидкість тут є причиною. А по-друге, я не розумію, що ви говорите: для повернення потрібно буде стільки ж прориву циклів, скільки і підвищення. Насправді ви можете уявити повернення як збір спеціального винятку Return, який завжди потрапляє в область виклику.
Veky

2
>> "збільшений розміром списку" Принаймні, якщо у вас немає сортування O (n), про який слід знати.
Джонатан Хартлі

106

Тому що у них різні випадки використання.

Цитуючи документи (Python 3.6):

Не впроваджений

повинні бути повернуті бінарними спеціальними методами (наприклад __eq__(), __lt__(), __add__(), __rsub__()і т.д.) , щоб вказати , що операція не здійснюється стосовно іншого типу

виняток NotImplementedError

[...] У базових класах, визначених користувачем, абстрактні методи повинні підвищувати цей виняток, коли вони вимагають, щоб похідні класи переосмислили метод, або коли клас розробляється, щоб вказати, що реальну реалізацію ще потрібно додати.

Деталі див. За посиланнями.


13

Однією з причин є продуктивність. У такій ситуації, як багаті порівняння, коли ви могли зробити багато операцій за короткий час, налаштування та обробка багатьох винятків може зайняти набагато більше часу, ніж просто повернути NotImplementedзначення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.