Необязательные и именованные аргументы

В Python аргументы функций могут иметь значения по умолчанию; если функция вызывается без аргумента, то он принимает своё значение по умолчанию. К тому же, аргументы можно указывать в любом порядке, задавая их имена.

Давайте ещё раз посмотрим на объявление функции approximate_size():

def approximate_size(size, a_kilobyte_is_1024_bytes=True):

Второй аргумент — a_kilobyte_is_1024_bytes — записывается со значением по умолчанию True. Это означает, что этот аргумент необязательный; можно вызвать функцию без него, а Python будет действовать так, как будто она вызвана с True в качестве второго параметра.

Теперь взглянем на последние строки скрипта:

if __name__ == '__main__':
print(approximate_size(1000000000000, False)) ①
print(approximate_size(1000000000000)) ②

Функция approximate_size() вызывается с двумя аргументами. Внутри функции approximate_size() переменная a_kilobyte_is_1024_bytes будет False, поскольку False передаётся явно во втором аргументе.
Функция approximate_size() вызывается только с одним аргументом. Но всё в порядке, потому что второй аргумент необязателен! Поскольку второй аргумент не указан, он принимает значение по умолчанию True, как определено в объявлении функции.

А ещё можно передавать значения в функцию по имени.

>>> from humansize import approximate_size
>>> approximate_size(4000, a_kilobyte_is_1024_bytes=False) ①
'4.0 KB'
>>> approximate_size(size=4000, a_kilobyte_is_1024_bytes=False) ②
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, size=4000) ③
'4.0 KB'
>>> approximate_size(a_kilobyte_is_1024_bytes=False, 4000) ④
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> approximate_size(size=4000, False) ⑤
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg

Перевод сообщений оболочки:

Файл "<stdin>", строка 1

SyntaxError: неименованный аргумент после именованного

Функция approximate_size() вызывается со значением 4000 в первом аргументе и False в аргументе по имени a_kilobyte_is_1024_bytes. (Он стоит на втором месте, но это не важно, как вы скоро увидите.)
Функция approximate_size() вызывается со значением 4000 в аргументе по имени size и False в аргументе по имени a_kilobyte_is_1024_bytes. (Эти именованные аргументы стоят в том же порядке, в каком они перечислены в объявлении функции, но это тоже не важно.)
Функция approximate_size() вызывается с False в аргументе по имени a_kilobyte_is_1024_bytes и 4000 в аргументе по имени size. (Видите? Я же говорил, что порядок не важен.)
Этот вызов не работает, потому что за именованным аргументом следует неименованный (позиционный). Если читать список аргументов слева направо, то как только встречается именованный аргумент, все следующие за ним аргументы тоже должны быть именованными.
Этот вызов тоже не работает, по той же причине, что и предыдущий. Удивительно? Ведь сначала передаётся 4000 в аргументе по имени size, затем, «очевидно», можно ожидать, что False станет аргументом по имени a_kilobyte_is_1024_bytes. Но в Python это не работает. Раз есть именованный аргумент, все аргументы справа от него тоже должны быть именованными.

Написание читаемого кода

Не буду растопыривать перед вами пальцы и мучить длинной лекцией о важности документирования кода. Просто знайте, что код пишется один раз, а читается многократно, и самый важный читатель вашего кода — это вы сами, через полгода после написания (т. е. всё уже забыто, и вдруг понадобилось что-то починить). В Python писать читаемый код просто. Используйте это его преимущество и через полгода вы скажете мне «спасибо».

Строки документации

Функции в Python можно документировать, снабжая их строками документации (англ. documentation string, сокращённо docstring). В нашей программе у функции approximate_size() есть строка документации:

def approximate_size(size, a_kilobyte_is_1024_bytes=True):
'''Преобразует размер файла в удобочитаемую для человека форму.

Ключевые аргументы:
size -- размер файла в байтах
a_kilobyte_is_1024_bytes -- если True (по умолчанию), используются степени 1024
если False, используются степени 1000

Возвращает: текстовую строку (string)

'''

Каждая функция заслуживает хорошую документацию.

Тройные кавычки[1] используются для задания строк[2] содержащих многострочный текст. Всё, что находится между начальными и конечными кавычками, является частью одной строки данных, включая переводы строк, пробелы в начале каждой строки текста, и другие кавычки. Вы можете использовать их где угодно, но чаще всего будете встречать их в определениях строк документации.

Тройные кавычки — это ещё и простой способ определить строку, содержащую одинарные (апострофы) и двойные кавычки, подобно qq/.../ в Perl 5.

Всё, что находится в тройных кавычках, — это строка документации функции, описывающая, что делает эта функция. Строка документации, если она есть, должна начинать тело функции, т. е. находится на следующей строчке сразу под объявлением функции. Строго говоря, вы не обязаны писать документацию к каждой своей функции, но всегда желательно это делать. Я знаю, что вам уже все уши прожужжали про документирование кода, но Python даёт вам дополнительный стимул — строки документации доступны во время выполнения как атрибут функции.