Palrom
Ну то есть, если бы не было last + 1, то range() внутри функции get_list() откинула бы последнее число в переданном ей диапазоне, а мы об этом и не узнали бы, потому, что детали функции скрыты от нас..
Мы бы об этом узнали, но нам пришлось бы переписывать слишком много в твоей версии кода.
Вот я, допустим, беру эту функцию, которую выложил здесь, и дорабатываю дальше
Было
def get_list(first, last, num):
out = []
for i in range(first, last + 1):
n = i
p = 1
for _ in range(3):
p *= n % 10
n //= 10
if p == num:
out.append(i)
return out
Стало
def get_list(first, last, num, ndigs):
out = []
for i in range(first, last + 1):
n = i
p = 1
for _ in range(ndigs):
p *= n % 10
n //= 10
if p == num:
out.append(i)
return out
Много мне пришлось поменять для этого? Нет, одно имя только.
Но вот что оно даёт, это одно имя
>>> def get_list(first, last, num, ndigs):
... out = []
... for i in range(first, last + 1):
... n = i
... p = 1
... for _ in range(ndigs):
... p *= n % 10
... n //= 10
... if p == num:
... out.append(i)
... return out
...
>>> get_list(1000, 2500, 8, 2)
[1018, 1024, 1042, 1081, 1118, 1124, 1142, 1181, 1218, 1224, 1242, 1281, 1318, 1324, 1342, 1381, 1418, 1424, 1442, 1481, 1518, 1524, 1542, 1581, 1618, 1624, 1642, 1681, 1718, 1724, 1742, 1781, 1818, 1824, 1842, 1881, 1918, 1924, 1942, 1981, 2018, 2024, 2042, 2081, 2118, 2124, 2142, 2181, 2218, 2224, 2242, 2281, 2318, 2324, 2342, 2381, 2418, 2424, 2442, 2481]
>>> get_list(1000, 2500, 8, 3)
[1118, 1124, 1142, 1181, 1214, 1222, 1241, 1412, 1421, 1811, 2118, 2124, 2142, 2181, 2214, 2222, 2241, 2412, 2421]
>>> get_list(1000, 2500, 8, 4)
[1118, 1124, 1142, 1181, 1214, 1222, 1241, 1412, 1421, 1811, 2114, 2122, 2141, 2212, 2221, 2411]
>>> get_list(1000, 2500, 8, 5)
[]
>>>
Что при первом создании этой функции, что при второй доработке этой функции сколько мне пришлось менять кода, который в ней содержится? Я просто заменил имена переменных
и всё сразу работает, даже проверять ничего не надо. Я могу не руками менять это, а написать скрипт, который возьмёт исходник, поменяет эти имена и сохранит исходник с новыми именами - сделает функции из отрывков кода. Ну, представь просто, что это код не одной такой функции, а ста таких функций - удобно менять это руками будет? Конечно же, нет, лучше скрипт написать.
А теперь возьми свой код и попробуй его поменять так быстро, превратить его в функции, встроить его в другую программу, чтобы с нуля код не писать и так далее. Во-первых, тебе придётся его очень досконально перечитывать, потому что у тебя везде там границы вот в таком виде - то они точные, то они неточные. А потом попробуй для такого кода скрипт написать, который его будет менять. Ты его руками замучаешься менять, а скриптом тем более. Тебе будет очень тяжело писать этот различитель, который будет понимать, где там правильно границы стоят, а где там неправильно границы стоят. Гораздо проще
и быстрее написать скрипт, который просто заменяет имена. Во-вторых, после того, как ты его досконально прочитаешь, тебе его придётся так же
досконально менять, чтобы переделать его в хорошо параметризированные функции, где параметры понятные и логичные, а не неизвестно как вычисляемые где-то там внутри функции. Так вот вот это всё тебе
нужно будеть ещё и описывать в документации к функции, если ты поленишься и не сделаешь параметры понятными и логичными.
То есть в итоге, из-за этого типа удобного кода, который ты в начале написал, ты три раза тратишь на него время потом. У него плохая реюзабельность. Он не может быть переиспользован. То есть тебе придётся все свои коды писать каждый раз с нуля. Ты не сможешь взять, допустим, готовую тысячу строк, которую ты написал там три года назад, и в ставить её в свой текущий проект в виде фрагмента без каких-либо существенных изменений, потому что, чтобы это сделать, тебе сначала нужно будет его как минимум переделывать три дня, так как в нём ничего не готово к повторному использованию - переиспользованию, реюзу.
tags: reusable code