Саммерфилд - Программирование на Python 3 (1077331), страница 45
Текст из файла (страница 45)
А если аргумент 1вт определен, используется он, как и в предыдущей версии функции. Такой прием, основанный на использовании значения по умолчанию Иопе и создании нового объекта, должен применяться к словарям, спискам, множествам и любым другим изменяемым типам данных, которые предполагается использовать в виде аргументов со значениями по умолчанию.
Ниже приводится немного более короткая версия функции, которая обладает тем же поведением: оет аррапс 11 ечеп(х, 1вт=нопе): 1вт = 1) тт 1вг 1в попа е1ве 1вт 1Г х % 2 == О; 1Ы. аррапп(х) гвтогп 1вт Использование условного выражения позволяет сократить размер функции на одну строку для каждого параметра, имеющего изменяемое значение по умолчанию. Имена и строки документирования Использование осмысленных имен для функций и их параметров помогает понимать назначение функции другим программистам, а также, 208 Глава 4.
Управляющие структуры и функции спустя некоторое время после создания функции, и самому автору функции. Ниже приводятся несколько основных правил, которых мы рекомендуем придерживаться. ° Используйте единую схему именования и придерживайтесь ее неуклонно. В этой книге имена ИМЕНА КОНСТАНТ записываются символами в верхнем регистре; имена Классов (и исключений) записываются символами верхнего и нижнего регистра, причем каждое слово в имени начинается с символа верхнего регистра; похожим образом записываются имена Функций и методов графического интерфейса, за исключением первого символа, который всегда записывается в нижнем регистре; а все остальные имена записываются только символами нижнего регистра или сиивопвми нижнего регистра с символом подчеркивания.
° Избегайте использовать аббревиатуры в любых именах, если эти аббревиатуры не являются стандартными и не получили широкого распространения. ° Соблюдайте разумный подход при выборе имен для переменных и параметров: имя х прекрасно подходит для координаты х, а имя т отлично подходит на роль переменной цикла, но вообще имена должны быть достаточно длинными и описательными.
Имя должно описывать скорее назначение элемента данных, чем его тип (например, имя ашоцпт Оце предпочтительнее, чем имя шопеу), если только имя не является универсальным для конкретного типа данных, например, имя параметра техт в функции впогтеп() (стр. 209). ° Имена функций и методов должны говорить о том, что они делают или что они возвращают (в зависимости от их назначения), и никогда — как они это делают, потому что эта характеристика может измениться со временем. Ниже приводятся несколько примеров имен: Пет Г1пв(1, в, т=0): в неуДАчный ВЫБОР Вет 1тпввг вввгсл(1, в, т=с): В НЕУДАЧНЫЙ ВЫБОР Пет Г1гвт швах ст(вогтве пвмв 11вт, паве, втагт=с): в хОРОшиЙ ВНБОР Все три функции возвращают индекс первого вхождения имени в списке имен, причем поиск в списке начинается с указанного индекса и используется алгоритм поиска, который предполагает, что список уже отсортирован.
Первый случай приходится признать неудачным, потому что имя функции ничего не говорит о том, что будут искать, а имена ее параметров (по всей видимости) указывают на их типы (1твт, втг, тпт), но ничего не говорят об их назначении. Второй вариант также следует признать неудачным, потому что имя функции описывает алгоритм, использованный первоначально, но с течением времени алгоритм могут изменить. Это может быть неважно для того, кто будет пользоваться функцией, но может вводить в заблуждение тех, кто будет сопрово- 209 Собственные функции ждать программный код, если имя функции предполагает реализацию алгоритма линейного поиска, а в действительности со временем функцию могли переписать под использование алгоритма поиска методом дихотомии.
Третий вариант можно назвать удачным, потому что имя функции говорит о том, что она возвращает, а имена параметров недвусмысленно показывают, что ожидает получить функция. Ни одна из функций не имеет возможности указать, что произойдет, если поиск завершится неудачей — вернут ли они, скажем, значение -1, или возбудят исключением В каком-то виде такая информация должна быть включена в описание, предоставляемое пользователям функции. Мы можем добавить описание к любой функции, используя строки документирования — это обычные строки, которые следуют сразу за строкой с инструкцией бе( и перед программным кодом функции.
Например, ниже приводится функция зйогсеп(), которую мы уже видели ранее, но на этот раз приводится полный ее текст: оет зпогтеп(техт, 1епдтп=25, тле!сатог="..."); """Возвращает техт или усеченную его копию с добавлением тпс1сатог в конце техт - любая строка; 1епдтп - максимальная длина возвращаемой с~роки зттпд (включая 1пс1сатог); тпс1сатог — строка, добавляемая в конец результата, чтобы показать, что текст аргумента техт был усечен »> зоогтеп("Тое Ноас") 'Тяе Вовс' »> зпогтеп("до соыптгу тог 01о деп", 20) 'ио Соыптгу тог 01...' »> зпогтеп("011>ез от тпе Р1атп", 15, "*") 'С!Нее от тое *' 11 1еп(техт) > 1епдтп: техт = техт(:1епдтп - 1еп(гпо1сатог)) + 1по1сатог гетогп техт Нет ничего необычного в том, что текст описания длиннее самой функции.
В соответствии с общепринятыми соглашениями первая строка в описании должна представлять собой краткое, однострочное описание функции, затем следует пустая строка и далее следует полное описание функции, в конце которого приводится несколько примеров того, как может выглядеть использование функции в интерактивной оболочке.
В главе б мы узнаем, как примеры, присутствующие в описании функции, могут использоваться для нужд модульного тестирования. г1б Глава 4. Управляющие структуры и функции Распаковывание аргументов и параметров В предыдущей главе мы видели, что для передачи позиционных аргументов можно использовать оператор распаковывания последовательностей (*). Например, если возникает необходимость вычислить площадь треугольника, а длины всех его сторон хранятся в списке, то мы могли бы вызвать функцию так: пегоп(810ев(0], в! сев(1], видев[2] ), или просто распаковать список и сделать вызов намного проще: г1егоп(*81оев). Если элементов в списке (или в другой последовательности) больше, чем параметров в функции, мы можем воспользоваться операцией извлечения среза, чтобы извлечь нужное число аргументов.
Мы можем также использовать оператор распаковывания последовательности в списке параметров функции. Это удобно, когда необходимо создать функцию, которая может принимать переменное число позиционных аргументов. Ниже приводится функция р гоп ос1( ), которая вычисляет произведение своих аргументов: оег ргооост(*вгдв): гево11 = 1 Гог егд (п вгдв: гево11 *= агд гетогп гево1т Эта функция имеет единственный аргумент с именем агдв. Наличие символа * перед ним означает, что внутри функции параметр а где обретает форму кортежа, значениями элементов которого будут значения переданных аргументов.
Ниже приводятся несколько примеров вызова функции: ргооост(1, г, 3, 4) в вгдв == (1, 2, 3, 4); вернет; 24 ргаоост(5, 3, 8) я вгдв == (5, 3, 8); вернет: 120 ргооост(11) ю агдв == (11,); вернет; 11 Мы можем использовать именованные аргументы вслед за позиционными, как в функции, которая приводится ниже, вычисляющей сумму своих аргументов, каждый из которых возводится в заданную степень: Оет вон от ронегв(*агдв, ронег=1): гево1т = 0 Гог вгд 1и вгдв: гево11 »= вгд * ронег гетогп гево11 Эта функция может вызываться только с позиционными аргументами, например: воз оу ронегв(1, 3, 5), или как с позиционными, так и с именованным аргументами, например: вов оу ронегв(1, 3, 5, ранет=2). Допускается также использовать символ «*» в качестве самостоятельного «параметра». В данном случае он указывает, что после символа Собственные функции «*» не может быть других позиционных параметров, однако указание именованных аргументов допускается.
Ниже приводится модифицированная версия функции Иегоп(). На этот раз функция принимает точно три позиционных аргумента и один необязательный именованный аргумент. оег пегоп2(а, и, с, *, опт!в="петегв"): в = (а » Ь + с) / 2 вгев = пвтп.всгт(в (в - в) ° (в - ь) (в — с)) гетогп "(0) (т)".тогювт(вгев, оп!1в) Ниже приводятся несколько примеров вызовов функции: Пегоп2(25, 24, 7) 4 вернет: '84.0 юетегз' пегоп2(4п 9, 40, оп11в="1пспев") 4 вернет: '180.0 1пспев' пегоп2(25, 24, 7, "тпопев") 4 ОшиБкА' Возбудит исключение турееггог В третьем вызове мы попытались передать четыре позиционных аргумента, но оператор * не позволяет этого и вызывает исключение ТуреЕггог.
Поместив оператор * первым в списке параметров, мы тем самым полностью запретим использование любых позиционных аргументов и вынудим тех, кто будет вызывать ее, использовать именованные аргументы. Ниже приводится пример сигнатуры такой (вымышленной) функции: оэт рг!п1 ветор(*. рврег="!е11эг", сор!ев=т, со1огеев1ве): Мы можем вызывать функцию рг!01 ве1ор() без аргументов, допуская использование значений по умолчанию. Или изменить некоторые или все значения по умолчанию, например: ргтп1 Ве1ор(рарег="А4", со)от= Тгое).