?

Log in

No account? Create an account

"-- А если чайник поный? -- Выливаем и далее по известному алгоритму." - Узором созвездий по мантии ночи

31.08.2011, Среда

01:05:00 - "-- А если чайник поный? -- Выливаем и далее по известному алгоритму."

Previous Entry Поделиться Next Entry

Прочитав, что в питоне проверка на наличие у объекта требуемого атрибута реализована через вызов метода получения значения атрибута и ловлю бросаемого им исключения, не мог не вспомнить упомянутый анекдот.
Особенно при том, что одно из очевидных применений -- это как раз проверка перед получением значения:

if hasattr(a, 'property'):
    do_something(a.property)


По-моему, какая-то противоестественная логика. Ну да, hasattr() избавляет нас от писания кода ловли исключения. Но всё-таки не слишком ли дофига лишних действий на этапе выполнения?

This entry was originally posted at http://arilou.dreamwidth.org/12288.html. Please comment there using OpenID.

Comments:

[User Picture]
From:taelhash
Date:30.08.2011 21:25:03
(Link)
Что-то я не понял, а в C++ код вида if(p) p->Do() не смущает? Целый if же...

Я вот в последнее время на LUA пишу, так у меня там код чуть более, чем наполовину, состоит из if x then print(x) end, либо if not x then return end; print(x), в зависимости от требуемого.
(Ответить) (Thread)
[User Picture]
From:arilou
Date:30.08.2011 21:57:11
(Link)
Ты действительно не понял. Совсем не понял. Претензия совсем не к необходимости писать if(), а к тому, как реализована проверка наличия атрибута.
(Ответить) (Parent) (Thread)
[User Picture]
From:taelhash
Date:31.08.2011 07:29:33
(Link)
И продолжаю не понимать. Чем плохо то, как реализована проверка наличия атрибута? Ты сказал, что бросание исключения чем-то плохо, и привел пример, в котором оно не бросается, в котором есть нелишний if, после чего сказано "не слишком ли много лишних действий"?

Какой-то очень странно сформулированный пост.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]
From:eramart
Date:30.08.2011 21:29:58
(Link)
нет ) на самом деле, правило "проще сделать, чем спросить" сильно упрощает код (ессно, в тех местах, где это не вредит производительности)
(Ответить) (Thread)
[User Picture]
From:arilou
Date:30.08.2011 21:57:52
(Link)
Я понимаю, что упрощает код. Но вот это уточнение в скобках как раз тут и выглядит нарушенным.
Я не случайно анекдот про алгоритм кипячения чайника напомнил в заголовке. ;)
(Ответить) (Parent) (Thread)
[User Picture]
From:eramart
Date:31.08.2011 04:59:57
(Link)
Думаю, что если те микросекунды, которые занимает проверка, критичны, надо менять питон на что-то более контролируемое.
(Ответить) (Parent) (Thread)
[User Picture]
From:phd
Date:30.08.2011 21:36:15
(Link)
Даже без hasattr необязательно ловить исключение:
ap = getattr(a, 'property', None)
if ap: do_something(ap)
PS. Сдвиг во второй строке своего кода поправь. ;-)
(Ответить) (Thread)
[User Picture]
From:phd
Date:30.08.2011 21:40:28
(Link)
Да, тут засада - а что, если a.property уже было None? Тогда придётся ставить стражника:
default = object()
ap = getattr(a, 'property', default)
if ap is not default: do_something(ap)
Ну или ловить исключение. :-)
(Ответить) (Parent) (Thread)
[User Picture]
From:arilou
Date:30.08.2011 21:51:19
(Link)
Это, мне кажется, случай более редкий -- когда есть смысловое различие между отсутствием атрибута и значением None. И что-то мне кажется, что введение такого различия в алгоритм (ну кроме случая отладочного кода, который как раз выясняет, а был ли установлен атрибут) -- повод остановиться, отложить работу и пойти выспаться. ;)
(Ответить) (Parent) (Thread)
[User Picture]
From:arilou
Date:30.08.2011 21:57:36
(Link)
Не сдвиг, а тэги в сообщении. ;)
(Ответить) (Parent) (Thread)
[User Picture]
From:phd
Date:31.08.2011 09:47:00
(Link)
Я сказал, что надо сделать, а ты - как. (-;
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]
From:besm6
Date:31.08.2011 08:47:03
(Link)
Если я правильно ошибаюсь, фишка питона - дешевые исключения. Так что if hasattr просто лишний. Но если ты пришел из тех мест, где исключения дорогие, и нервничаешь, то можно написать if hasattr. Результат тот же, но тебе спокойнее.
(Ответить) (Thread)
[User Picture]
From:arilou
Date:31.08.2011 13:33:18
(Link)
Насколько я понял из документации (и видимо как-то коряво изложил тут), внутри hasattr дёргается всё тот же getattr и ловится исключение (так что никуда я от него не денусь). Что и вызвало этот пост. Мне как-то искренне казалось, что разумно было бы в hasattr дёргать тот же алгоритм поиска атрибута, что и в getattr, а по результату поиска просто возвращать, получилось или нет. А за одно и не трогать значение атрибута. Ведь если getattr его возвращает - то при этом, видимо, увеличивается счётчик ссылок, а потом (поскольку значение никуда не присваивается), счётчик обратно уменьшается.

А использование функции проверки вместо ловли исключения удобнее тем, что можно применять в выражениях. Да, тринарный оператор в питоне сначала за что-то не взлюбили, а потом сделали ему извращённую замену. Ну да хоть так.
Не люблю, когда простое по смыслу действие приходится расписывать на много строк. Код становится громоздким и рыхлым.
(Ответить) (Parent) (Thread)
[User Picture]
From:besm6
Date:31.08.2011 16:13:10
(Link)
А как ты будешь использовать тот же алгоритм поиска, если getattr (вернее, __getattr__) у тебя переопределен? Кроме как вызовом оного getattr? Алгоритм-то нигде больше не изложен, кроме как в твоем переопределенном __getattr__...

Ну и эта... Схема работы с исключениями вообще такова, что ты вместо тернарного выражения пишешь просто получение атрибута, а ситуацию "если его нет" ловишь в совершенно другом месте. А если ты проверку делал для того, чтобы подставить умолчание в случае отсутствия атрибута, то затем у getattr и третий параметр.

Что там остается из разумного? "<b>".name vs. "<i>имя не определено"? Это уже достойно своей отдельной функции, где ты будешь работать с исключением по модели работы с исключениями. Потому что по смыслу это уже имя_с_форматированием_и_обработкой_отсутствия(), а конкретные b и i завтра потребуется при запросе, отличающемся двумя буквами, превратить в strong и emph, и оно тебе надо, разыскивать их по всему коду?
(Ответить) (Parent) (Thread)
[User Picture]
From:arilou
Date:31.08.2011 17:47:16
(Link)
Н-да... Ну вот переопределение -- это повод, согласен. Ощущение кривизны, конечно, никуда не делось, но по крайеней мере теперь она объяснима. Спасибо.

Хотя почитал сейчас внимательнее -- там же ещё хитрее. __getattr__ вызывается после облома стандартного способа поиска атрибута, но есть ещё и __getattribute__, у которого тоже есть случай, когда он не вызывается, причём оба могут швырять AttributeError... Как весело жить! ;)

Edited at 2011-08-31 17:48 (UTC)
(Ответить) (Parent) (Thread) (Развернуть)