Pull to refresh

Comments 48

5.2.1. Уточнение
Использование именованных аргументов и произвольного числа обычных аргументов одновременно, по-видимому, невозможно, потому что именованные аргументы должны быть определены до "*"-параметра. Например, представим функцию:

А как же стандартное
def x(a,b, *args, **kwargs):
    pass
x(1,2,'a','b',named='123',named2='456')

Полагаю, правильно было бы написать что-то вроде «использование неименованных аргументов _после_ именованных»
Мало каметариев… Судя по всему многие мало что поняли из написанного.

Я лично выкрутил мозг на этом абзаце

«4.2. Уловка and/or

«and» и «or» в Python — сложные создания. Применение and к нескольким выражениям не просто возвращает True или False. Оно возвращает первое false-выражение, либо последнее из выражений, если все они true. Результат ожидаем: если все выражения верны, возвращается последнее, являющееся true; если одно из них false, оно и возвращается и преобразуется к False при проверке логического значения. „
Просто понять на примере:
'' — False, пустая сторка
0 — False
[] — False, пустой список

'habr' — True
1337, -1, 5 — все True
[(a,b),(c,d)] — все True

'habr' and 5 == 5 (последнее из выражений, если все они true)
'habr' and [] == [] (первое false-выражение)
0 and '' == 0 (первое false-выражение)

0 or '' == ''
'habr' or 0 == 'habr'
[] or 1 == 1
Да, 4.2 напрягает мозг и заставляет лезть в документацию :-)

result = test and 'Test is True' or 'Test is False'

Сначала нужно определиться с приоритетом логических операторов (http://docs.python.org/library/stdtypes.html#boolean-operations-and-or-not). В порядке убывания он такой — not, and, or. Значит выражение можно записать так:

result = (test and 'Test is True') or 'Test is False'

Теперь нужно понять, как интерпретируются значения операндов в контексте логических операторов (http://docs.python.org/reference/expressions.html#boolean-operations). Из первого абзаца становится ясно, что False, None, 0, 0.0, '', (), [], {}, set() интерпретируется как ложь, все остальное как истина. Значит, строки 'Test is True' и 'Test is False' интерпретируются как истина.

test = True

Читаем 3 абзац в последней ссылке и понимаем, что в случае выражения test and 'Test is True', если оба аргумента интерпретируются как истина, то оператор вернет значение второго аргумента, то есть строку 'Test is True'.

Из четвертого абзаца в той же ссылке понимаем, что 'Test is True' or 'Test is False' вернет значение первого аргумента, т.е. 'Test is True'.

test = False

test and 'Test is True' вернет False без заморочек, а False or 'Test is False' конечно второй аргумент, 'Test is False'

Да, про то, что логические операторы возвращают не True и False, а значения самих операндов, написано в последнем абзаце в той же ссылке.
По поводу пункта 4.2 можно было бы явно указать, что логические операторы возвращают объект, а не логическую величину:

print (True or object()).__class__
print (False or object()).__class__
UFO just landed and posted this here
Прямо-таки пересказ? Riateche добросовестно (и при том достаточно качественно) переводит весьма интересную статью. Если же Вы намекаете на то, что все эти tips-ы так или иначе описаны в документации к Питону, то Вы совершенно правы.
Но согласитесь: выуживать эти хитрости по одной оттуда — дело не самое приятное. А по сравнению с возможностями многих других языков большую часть описанного кроме как хаками и трюками никак и не назовешь.

Вобщем так держать и большое спасибо за перевод… и еще большее — за линк на оригинал =)
UFO just landed and posted this here
Может быть, в этом фрагменте статьи хаков мало, но в первых двух частях они точно были.

Вещи действительно несложные, но они затрагиваются в приличных книжках, поэтому мне о них писать тоже можно.
UFO just landed and posted this here
Мне кажется, что писать с использованием недокументированных возможностей языка можно только при крайней необходимости. Для Python я это смутно себе представляю, язык довольно гибкий.
В 5.2 второй кусок кода == первому, а должен быть явно другим.
А за статью спасибо! Жду продолжения.
UFO just landed and posted this here
> что дефолтные значения аргументов функции выполняются только один раз

коряво сказано, имхо. значения выполняются или определения?
def func(item, stuff=()):
… stuff = list(stuff)
… stuff.append(item)
… print stuff

а так не будет удобней? чтоб не использовать иф?
О, круто. Не приходило такое в голову :)
Даже так будет корректно работать:
    def func(item, stuff=()):
        stuff = dict(stuff)
просто часто вижу этот пример со словарем и None и мне так не нравится этот пример
Ну, фиг знает. Я хорошо помню, что кортежный кортеж диктится. Оно же часто используется для «генератора словарей» :)
UFO just landed and posted this here
Кортежный кортеж это {}.items(). Список кортежей :)
Респект за перевод.

А сама глава надуманная какая-то. Вряд ли стоит использовать неочевидности из 4.2 и 4.3. Во всяком случае, я их успешно забыл и не жалею.

Тоже самое касается @resetDefaults. Одноразовое вычисление значений всё равно нужно держать в голове, чтобы этот декоратор не удивлял.

Вообще от статьи ощущение, что автор не долго на питоне кодит. Не юзает свои же советы:
    if stuff is None:
        stuff = []

Равно: stuff = [] if stuff is None else stuf

По кваргсам примеры надуманные. Есть куча практических примеров, типа:
def __init__(self, **kw):
    (setattr(self, k, v) for k, v in kw.iteritems())
Ой, конечно так: [setattr(self, k, v) for k, v in kw.iteritems()]
Хехе, ничо что я тут онанирую?
    def __init__(self, **kw):
        self.__dict__.update(kw)
UFO just landed and posted this here
Ну, это может быть самостоятельным классом для превращения дикта в объект :)
Равно: stuff = [] if stuff is None else stuf

Или даже
stuff = stuff or []
Вообще мне кажется, что знание, например, Си, делает множество высокоуровневых языков практически очевидными.
Ага, если нам не жалко потерять '', {} и т.п.
Не жалко, потому что у нас должен быть либо массив, либо None. Ничего другого быть не должно по условию.
Имхо, автор не юзает свои же советы, потому что хочет сделать примеры максимально понятными.
Ну вот о том и речь, что его советы делают код непонятным :)
Мало и менее полезно, чем предыдущие части.
Так же как-то совсем скомкана часть про передачу списка или словаря в качестве переменных — всего один пример и тот не показательный. В документации как-то попонятнее.

Но — спасибо за сам цикл статей!
Если уж цикл дошёл до тернарного оператора, тогда вы забыли про switch case.
Как-то так:
case = {
   'case1': case1_result,
   'case2': case2_result
   }[case_value]
UFO just landed and posted this here
>>> func = lambda x: print(x)
>>> {'case1': lambda: func('fail1'),
...  'case2': lambda: func('fail2')}['case2']()
fail2
UFO just landed and posted this here
print(x) печатает x
просто def func… заменил на лямбду для краткости

еще вы кажется не понимаете как работают списки — значения в них вычисляются перед использованием и даже простое объявление {«case1»: func(«fail1»), «case2»: func(«fail2»)} выведет fail1 и fail2

по этому нужно поместить в списки функцию, а потом ее вызывать, что я и сделал через лямбды
Верно, но это уже слишком громоздко.
в данном случае да, для: {'case1': func1, 'case2': funct2}['case1'](params) удобнее, но не так часто используется
и короче чем if:… elif:… elif:… за счет отсутствия переноса строк в любом случае, даже, несколько более читабельнее по-моему
UFO just landed and posted this here
в примере siasia все будет хорошо, и если case1_result будут фунциями и если переменными, но замечание полезное :)
Чтоб не путаться в if… else и в or… and и не «испытывать смешанных чувств» лучше всё-таки не полениться и расставить скобочки для ясности. Чтоб ещё и не мучаться, вспоминая приоритеты операторов.
да с [] в парамерах по умалчанию унесло не один час моего времени ))))
Да, ещё одно: не многие знают, что в слайсы можно передавать 3 значения, например list(range(10))[::2] в python3 или range(10)[::2] в 2.5 выведут все парные числа до 10ти. range(10)[1::2] — непарные
А еще этот третий параметр (шаг) может быть отрицательным, тогда элементы в срез попадут в обратном порядке.
А еще в Python можно сохранять слайсы для последующего применения:
my_slice = slice(None, None, -1)
'hello'[my_slice]
'olleh'
Sign up to leave a comment.

Articles