Комментарии 36
Также совершенно нe к месту
assert
в теле функции, который работает лишь при заданном __debug__
.+2
Наоборот, он не работает при включенных оптимизациях (никогда не видел, чтобы кто-то их включал). Более того, это очень правильный способ проверить, что что-то не так.
+1
Так я о том же и написал.
__debug__ == False
при загрузке кода из *.pyo файла. https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement. 0
assert
в данном случае используется неправильно, по очень простой причине: он производит валидацию значений входных данных, чем должна заниматься бизнес-логика. assert
нужен в качестве инструмента для поиска ошибок программиста, например:assert isinstance(k, int), 'Invalid input "k" argument type in template(), should be int, received %s' % type(k)
+1
А я видел. Например, anki под win32.
Отладка была мучительной, потому что внутри assert происходил какой-то побочный эффект.
Итого, проверять assert'ом нужно только то, что не должно происходить в программе никогда. Неправильные аргументы функции нужно проверять if'ом с вызовом исключения в случае необходимости.
Отладка была мучительной, потому что внутри assert происходил какой-то побочный эффект.
Итого, проверять assert'ом нужно только то, что не должно происходить в программе никогда. Неправильные аргументы функции нужно проверять if'ом с вызовом исключения в случае необходимости.
+4
Выразительная простота python
Я не осилил этот код в течении нескольких минут не смотря на то, что сам когда то ради интереса писал подобное. Не осилил потому что постоянно натыкался на странные слова template, reducer, assertion и пытался понять а что это за хрень такая и зачем она может быть нужна. Возможно с более интуитивно понятными именами получилось бы нагляднее.
+5
n = len(s)
...
for i in range(n):
c = s[i]
Откройте для себя enumerate.
На самом деле Ваш код просто ужасен. Автор, извините, но у Вас C++ головного мозга, на python так не пишут. Pythonic-код — это понятный, легко-читаемый код с нормальными именами переменных, Вы же, видимо, стремились к максимально короткому и насыщенному лишними абстракциями коду.
+3
Не могли бы вы написать это на питоне как надо? Я сам о питоне только слышал и поэтому любопытствую.
0
for index, item in enumerate(n):
c = item
c = item
+1
Конкретно этот код автора вот так можно переписать:
Особо в код не вчитывался, может там вообще всё можно переписать. Сейчас код автора выглядит плохо. На Python так не пишут.
for i, c in enumerate(s):
...
Особо в код не вчитывался, может там вообще всё можно переписать. Сейчас код автора выглядит плохо. На Python так не пишут.
+3
А как надо можно узнать?
0
Но в общем, переменные с ничего не говорящими именами
s
, k
, c
, new_s
— это уровень первого курса. Если Вы сейчас закроете эту страницу и откроете её через пару месяцев, то может и Вам код покажется нечитаемым и непонятным. Очень рекомендую «Code complete» («Совершенный код» в русском переводе) для улучшения навыков написания красивого кода. 0
То есть ваши претезии только к форме, а не к содержанию? Насчет названия переменнных, что такое k, n должно быть понятно из таблицы над кодом(это стандартные обозначения в комбинаторике), а s для стороки и с для символа тоже не редкость
0
Нет, к содержанию тоже есть претензии. Я бы изначально написал каждую функцию по-отдельности, не используя общие template, с передачей в него пары лямбда-выражений.
+1
А можно продолжить мысль и объяснить почему?
0
Такой код было бы гораздо легче читать. Т.е. представьте себя на месте человека, который не особенно знаком с комбинаторикой и разбирает Ваш код. Он начинает с
Вот как например будет выглядеть целостная
permutation_norep()
. Тут же он сталкивается с тем, что далее идёт вызов template()
да ещё с двумя аргументами-функциями. Хорошо, идём дальше в глубину template()
… Опа, assertion()
. Так, а что там за assertion()
был? Ага, n
и k
дожны быть положительными, либо равны нулю, причём n >= k
. Далее — reducer()
. А что там этот reducer
делает?.. Думаю, Вы поняли мысль. Вот как например будет выглядеть целостная
permutation_norep
:def permutation_norep(s, k):
len_s = len(s)
is_valid_input = len_s > 0 and len_s >= k and k >= 0
if not is_valid_input:
raise ValueError('Invalid input: s={}, k={}'.format(s, k))
if k == 0:
yield ""
return
k <= 1:
yield from s
return
new_k = k - 1
for i in range(len_s):
new_s = s[:i] + s[i + 1:]
for res in permutation_norep(new_s, new_k):
yield s[i] + res
+1
Тьфу ты, в коде
elif
потерял (там, где k == 1
).0
Хорошо… Но задача написать не одну функцию, а четыре. Как я упомянул в своем посте, сначала были написанны все 4 функции подобным образом. Когда перед тобой 4 почти одинаковые функции, а различия в состоят в двух строках кода, появляется естественное желание выделить общее. Такой код намного проще сопровождать, Что бы заменить assert на if(как вы предлагаете ), например, мне нужно одно изменение, а не в четыре. Шаблоны проектирования придуманы не мной, и не один я ими пользуюсь… Так что может ваш код и более «питонистый», но с точки зрения вопроса проектирования я вижу большой минус.
0
Я думал об этом, когда писал предыдущий ответ и решил, что я в данном случае я остановился бы на 4-х функциях. Спросите себя, неужто так много усилий стоит поддерживать конкретно эти функции? Скорее всего Вы напишете их и забудете надолго, до тех пор, пока не надо будет внести кардинальные изменения. Опять таки, это не должно занять так много времени, ведь функции по-сути одинаковые.
При всём, я согласен, что в других случаях такой подход совершенно неприемлим и логичнее использовать пострение через шаблон.
При всём, я согласен, что в других случаях такой подход совершенно неприемлим и логичнее использовать пострение через шаблон.
0
Если взглянуть на itertools.combinations(iterable, r) то там тоже присутствует однабуквенная переменная…
0
Хотел бы взглянуть на просто прекрасный код…
0
>> поэтому он позволяет проще и выразительнее писать код, который бы на других языках выглядел бы более громоздко и запутаннее
Не обощайте: www.ruby-doc.org/core-2.1.2/Array.html#method-i-permutation
Не обощайте: www.ruby-doc.org/core-2.1.2/Array.html#method-i-permutation
0
Кат бы не помешал.
+2
Лично мне в качестве примера выразительности Питона больше нравится заметка Питера Норвига о решалке судоку.
+1
Господа критики, критика должна быть конструктивной. Выражения типа «код автора выглядит плохо. На Python так не пишут», «Ваш код просто ужасен» и т.д. без конкретных замечаний и реализаций смотрятся странно. Критикуя-предлагай.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Выразительная простота python на примере задач из комбинаторики