Главная страница
Навигация по странице:

  • УПРАЖНЕНИЯ 8.3. Футболка

  • 8.5. Города

  • Изучаем Python Эрик Метиз. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g


    Скачать 6.19 Mb.
    НазваниеCrash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
    Дата22.09.2022
    Размер6.19 Mb.
    Формат файлаpdf
    Имя файлаИзучаем Python Эрик Метиз.pdf
    ТипДокументы
    #690181
    страница17 из 52
    1   ...   13   14   15   16   17   18   19   20   ...   52
    147
    Функция может иметь любое количество позиционных аргументов. При вызове функции Python перебирает аргументы, приведенные в вызове, и сопоставляет каждый аргумент с соответствующим параметром из определения функции.
    О важности порядка позиционных аргументов
    Если нарушить порядок следования аргументов в вызове при использовании по- зиционных аргументов, возможны неожиданные результаты:
    def describe_pet(animal_type, pet_name):
    """Выводит информацию о животном."""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
    describe_pet('harry', 'hamster')
    В этом вызове функции сначала передается имя, а потом тип животного. Так как аргумент 'harry'
    находится в первой позиции, значение сохраняется в параметре animal_type
    , а аргумент 'hamster'
    — в pet_name
    . На этот раз вывод получается бессмысленным:
    I have a harry.
    My harry's name is Hamster.
    Если вы получили подобные странные результаты, проверьте, что порядок сле- дования аргументов в вызове функции соответствует порядку параметров в ее определении.
    Именованные аргументы
    Именованный аргумент представляет собой пару «имя-значение», передаваемую функции. Имя и значение связываются с аргументом напрямую, так что при пере- даче аргумента путаница с порядком исключается. Именованные аргументы из- бавляют от хлопот с порядком аргументов при вызове функции, а также проясняют роль каждого значения в вызове функции.
    Перепишем программу pets .py с использованием именованных аргументов при вызове describe_pet()
    :
    def describe_pet(animal_type, pet_name):
    """Выводит информацию о животном."""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
    describe_pet(animal_type='hamster', pet_name='harry')
    Функция describe_pet()
    не изменилась. Однако на этот раз при вызове функции мы явно сообщаем Python, с каким параметром должен быть связан каждый аргу-

    148 Глава 8 • Функции мент. При обработке вызова функции Python знает, что аргумент 'hamster'
    должен быть сохранен в параметре animal_type
    , а аргумент 'harry'
    — в параметре pet_name
    Порядок следования именованных аргументов в данном случае неважен, потому что Python знает, где должно храниться каждое значение. Следующие два вызова функции эквивалентны:
    describe_pet(animal_type='hamster', pet_name='harry')
    describe_pet(pet_name='harry', animal_type='hamster')
    ПРИМЕЧАНИЕ При использовании именованных аргументов будьте внимательны — имена должны точно совпадать с именами параметров из определения функции .
    Значения по умолчанию
    Для каждого параметра вашей функции можно определить значение по умолча- нию. Если при вызове функции передается аргумент, соответствующий данному параметру, Python использует значение аргумента, а если нет — использует зна- чение по умолчанию. Таким образом, если для параметра определено значение по умолчанию, вы можете опустить соответствующий аргумент, который обычно включается в вызов функции. Значения по умолчанию упрощают вызовы функций и проясняют типичные способы использования функций.
    Например, если вы заметили, что большинство вызовов describe_pet()
    использу- ется для описания собак, задайте animal_type значение по умолчанию 'dog'
    . Теперь в любом вызове describe_pet()
    для собаки эту информацию можно опустить:
    def describe_pet(pet_name, animal_type='dog'):
    """Выводит информацию о животном."""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
    describe_pet(pet_name='willie')
    Мы изменили определение describe_pet()
    и включили для параметра animal_type значение по умолчанию 'dog'
    . Если теперь функция будет вызвана без указания animal_type
    , Python знает, что для этого параметра следует использовать значе- ние 'dog'
    :
    I have a dog.
    My dog's name is Willie.
    Обратите внимание: в определении функции пришлось изменить порядок параме- тров. Так как благодаря значению по умолчанию указывать аргумент с типом жи- вотного не обязательно, единственным оставшимся аргументом в вызове функции остается имя домашнего животного. Python интерпретирует его как позиционный аргумент, и если функция вызывается только с именем животного, этот аргумент ставится в соответствие с первым параметром в определении функции. Именно по этой причине имя животного должно быть первым параметром.

    Передача аргументов 149
    В простейшем варианте использования этой функции при вызове передается только имя собаки:
    describe_pet('willie')
    Вызов функции выводит тот же результат, что и в предыдущем примере. Един- ственный переданный аргумент 'willie'
    ставится в соответствие с первым параме- тром в определении, pet_name
    . Так как для animal_type аргумент не указан, Python использует значение по умолчанию 'dog'
    Для вывода информации о любом другом животном, кроме собаки, используется вызов функции следующего вида:
    describe_pet(pet_name='harry', animal_type='hamster')
    Так как аргумент для параметра animal_type задан явно, Python игнорирует зна- чение параметра по умолчанию.
    ПРИМЕЧАНИЕ Если вы используете значения по умолчанию, все параметры со зна- чением по умолчанию должны следовать после параметров, у которых значений по умолчанию нет . Это необходимо для того, чтобы Python правильно интерпретировал позиционные аргументы .
    Эквивалентные вызовы функций
    Так как позиционные аргументы, именованные аргументы и значения по умолча- нию могут использоваться одновременно, часто существуют несколько эквива- лентных способов вызова функций. Возьмем следующий оператор describe_pets()
    с одним значением по умолчанию:
    def describe_pet(pet_name, animal_type='dog'):
    При таком определении аргумент для параметра pet_name должен задаваться в лю- бом случае, но это значение может передаваться как в позиционном, так и в име- нованном формате. Если описываемое животное не является собакой, то аргумент animal_type тоже должен быть включен в вызов, и этот аргумент тоже может быть задан как в позиционном, так и в именованном формате.
    Все следующие вызовы являются допустимыми для данной функции:
    # Пес по имени Вилли.
    describe_pet('willie')
    describe_pet(pet_name='willie')
    # Хомяк по имени Гарри. describe_pet('harry', 'hamster')
    describe_pet(pet_name='harry', animal_type='hamster')
    describe_pet(animal_type='hamster', pet_name='harry')
    Все вызовы функции выдадут такой же результат, как и в предыдущих примерах.

    150 Глава 8 • Функции
    ПРИМЕЧАНИЕ На самом деле не так важно, какой стиль вызова вы используете . Если ваша функция выдает нужный результат, выберите тот стиль, который вам кажется более понятным .
    Предотвращение ошибок в аргументах
    Не удивляйтесь, если на первых порах вашей работы с функциями будут встре- чаться ошибки несоответствия аргументов. Такие ошибки происходят в том слу- чае, если вы передали меньше или больше аргументов, чем необходимо функции для выполнения ее работы. Например, вот что произойдет при попытке вызвать describe_pet()
    без аргументов:
    def describe_pet(animal_type, pet_name):
    """Выводит информацию о животном."""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")
    describe_pet()
    Python понимает, что при вызове функции часть информации отсутствует, и мы видим это в данных трассировки:
    Traceback (most recent call last):

    File "pets.py", line 6, in

    describe_pet()

    TypeError: describe_pet() missing 2 required positional arguments: 'animal_
    type' and 'pet_name'
    В точке  сообщается местонахождение проблемы, чтобы вы поняли, что с вызовом функции что-то пошло не так. В точке  приводится вызов функции, приведший к ошибке. В точке  Python сообщает, что при вызове пропущены два аргумента, и сообщает имена этих аргументов. Если бы функция размещалась в отдельном файле, вероятно, вы смогли бы исправить вызов и вам не пришлось бы открывать этот файл и читать код функции.
    Python помогает еще и тем, что он читает код функции и сообщает имена аргумен- тов, которые необходимо передать при вызове. Это еще одна причина для того, чтобы присваивать переменным и функциям содержательные имена. В этом случае сообщения об ошибках Python принесут больше пользы как вам, так и любому другому разработчику, который будет использовать ваш код.
    Если при вызове будут переданы лишние аргументы, вы получите похожую трасси- ровку, которая поможет привести вызов функции в соответствие с ее определением.
    УПРАЖНЕНИЯ
    8.3. Футболка: напишите функцию make_shirt()
    , которая получает размер футболки и текст, который должен быть напечатан на ней. Функция должна выводить сообщение с размером и текстом.

    Возвращаемое значение 151
    Вызовите функцию с использованием позиционных аргументов. Вызовите функцию во второй раз с использованием именованных аргументов.
    8.4. Большие футболки: измените функцию make_shirt()
    , чтобы по умолчанию футболки имели размер L и на них выводился текст «I love Python». Создайте футболку с размером L и текстом по умолчанию, а также футболку любого размера с другим текстом.
    8.5. Города: напишите функцию describe_city()
    , которая получает названия города и страны. Функция должна выводить простое сообщение (например, «Reykjavik is in
    Iceland»). Задайте параметру страны значение по умолчанию. Вызовите свою функцию для трех разных городов, по крайней мере один из которых не находится в стране по умолчанию.
    Возвращаемое значение
    Функция не обязана выводить результаты своей работы напрямую. Вместо этого она может обработать данные, а затем вернуть значение или набор сообщений.
    Значение, возвращаемое функцией, называется возвращаемым значением. Команда return передает значение из функции в точку программы, в которой эта функция была вызвана. Возвращаемые значения помогают переместить большую часть рутинной работы в вашей программе в функции, чтобы упростить основной код программы.
    Возвращение простого значения
    Рассмотрим функцию, которая получает имя и фамилию и возвращает аккуратно отформатированное полное имя:
    formatted_name.py

    def get_formatted_name(first_name, last_name):
    """Возвращает аккуратно отформатированное полное имя."""

    full_name = f"{first_name} {last_name}"

    return full_name.title()

    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)
    Определение get_formatted_name()
    получает в параметрах имя и фамилию .
    Функция объединяет эти два имени, добавляет между ними пробел и сохраняет результат в full_name
    . Значение full_name преобразуется в формат с начальной буквой верхнего регистра, а затем возвращается в точку вызова .
    Вызывая функцию, которая возвращает значение, необходимо предоставить пере- менную, в которой должно храниться возвращаемое значение. В данном случае возвращаемое значение сохраняется в переменной musician
    . Результат содержит аккуратно отформатированное полное имя, построенное из имени и фамилии:
    Jimi Hendrix

    152 Глава 8 • Функции
    Может показаться, что все эти хлопоты излишни — с таким же успехом можно было использовать команду:
    print("Jimi Hendrix")
    Но если представить, что вы пишете большую программу, в которой многочис- ленные имена и фамилии должны храниться по отдельности, такие функции, как get_formatted_name()
    , становятся чрезвычайно полезными. Вы храните имена отдельно от фамилий, а затем вызываете функцию везде, где потребуется вывести полное имя.
    Необязательные аргументы
    Иногда бывает удобно сделать аргумент необязательным, чтобы разработчик, ис- пользующий функцию, мог передать дополнительную информацию только в том случае, если он этого захочет. Чтобы сделать аргумент необязательным, можно воспользоваться значением по умолчанию.
    Допустим, вы захотели расширить функцию get_formatted_name()
    , чтобы она также работала и со вторыми именами. Первая попытка могла бы выглядеть так:
    def get_formatted_name(first_name, middle_name, last_name):
    """Возвращает аккуратно отформатированное полное имя."""
    full_name = f"{first_name} {middle_name} {last_name}"
    return full_name.title()
    musician = get_formatted_name('john', 'lee', 'hooker')
    print(musician)
    Функция работает при получении имени, второго имени и фамилии. Она получает все три части имени, а затем строит из них строку. Функция добавляет пробелы там, где это уместно, и преобразует полное имя в формат с капитализацией:
    John Lee Hooker
    Однако вторые имена нужны не всегда, а в такой записи функция не будет работать, если при вызове ей передается только имя и фамилия. Чтобы средний аргумент был необязательным, можно присвоить аргументу middle_name пустое значение по умолчанию; этот аргумент игнорируется, если пользователь не передал для него значение. Чтобы функция get_formatted_name()
    работала без второго имени, сле- дует назначить для параметра middle_name пустую строку значением по умолчанию и переместить его в конец списка параметров:

    def get_formatted_name(first_name, last_name, middle_name=''):
    """Возвращает аккуратно отформатированное полное имя."""

    if middle_name:
    full_name = f"{first_name} {middle_name} {last_name}"

    else:
    full_name = f"{first_name} {last_name}"
    return full_name.title()

    Возвращаемое значение 153
    musician = get_formatted_name('jimi', 'hendrix')
    print(musician)

    musician = get_formatted_name('john', 'hooker', 'lee')
    print(musician)
    В этом примере имя строится из трех возможных частей. Поскольку имя и фамилия указываются всегда, эти параметры стоят в начале списка в определении функции.
    Второе имя не обязательно, поэтому оно находится на последнем месте в опреде- лении, а его значением по умолчанию является пустая строка .
    В теле функции мы сначала проверяем, было ли задано второе имя. Python интер- претирует непустые строки как истинное значение, и если при вызове задан аргумент второго имени, middle_name дает результат
    True
    . Если второе имя указано, то из имени, второго имени и фамилии строится полное имя. Затем имя преобразуется с капитализацией символов и возвращается в строку вызова функции, где оно со- храняется в переменной musician и выводится. Если второе имя не указано, то пустая строка не проходит проверку if и выполняет блок else
    . В этом случае полное имя строится только из имени и фамилии и отформатированное имя возвращается в строку вызова, где оно сохраняется в переменной musician и выводится.
    Вызов этой функции с именем и фамилией достаточно тривиален. Но при ис- пользовании второго имени придется проследить за тем, чтобы второе имя было последним из передаваемых аргументов. Это необходимо для правильного связы- вания позиционных аргументов в строке .
    Обновленная версия этой функции подойдет как для людей, у которых задается только имя и фамилия, так и для людей со вторым именем:
    Jimi Hendrix
    John Lee Hooker
    Необязательные значения позволяют функциям работать в максимально широком спектре сценариев использования без усложнения вызовов.
    Возвращение словаря
    Функция может вернуть любое значение, которое вам потребуется, в том числе и более сложную структуру данных (например, список или словарь). Так, следующая функция получает части имени и возвращает словарь, представляющий человека:
    person.py
    def build_person(first_name, last_name):
    """Возвращает словарь с информацией о человеке."""

    person = {'first': first_name, 'last': last_name}

    return person musician = build_person('jimi', 'hendrix')

    print(musician)

    154 Глава 8 • Функции
    Функция build_person()
    получает имя и фамилию и сохраняет полученные зна- чения в словаре в точке . Значение first_name сохраняется с ключом 'first'
    , а значение last_name
    — с ключом 'last'
    . Весь словарь с описанием челове- ка возвращается в точке . Возвращаемое значение выводится в точке  с дву- мя исходными фрагментами текстовой информации, теперь хранящимися в сло- варе:
    {'first': 'jimi', 'last': 'hendrix'}
    Функция получает простую текстовую информацию и помещает ее в более удоб- ную структуру данных, которая позволяет работать с информацией (помимо про- стого вывода). Строки 'jimi'
    и 'hendrix'
    теперь помечены как имя и фамилия.
    Функцию можно легко расширить так, чтобы она принимала дополнительные значения — второе имя, возраст, профессию или любую другую информацию о че- ловеке, которую вы хотите сохранить. Например, следующее изменение позволяет также сохранить возраст человека:
    def build_person(first_name, last_name):
    """Возвращает словарь с информацией о человеке."""
    person = {'first': first_name, 'last': last_name}
    if age:
    person['age'] = age return person musician = build_person('jimi', 'hendrix', age=27)
    print(musician)
    В определение функции добавляется новый необязательный параметр age
    , кото- рому присваивается специальное значение по умолчанию
    None
    — оно используется для переменных, которым не присвоено никакое значение. При проверке условий
    None интерпретируется как
    False
    . Если вызов функции включает значение этого параметра, то значение сохраняется в словаре. Функция всегда сохраняет имя, но ее также можно модифицировать, чтобы она сохраняла любую необходимую информацию о человеке.
    Использование функции в цикле while
    Функции могут использоваться со всеми структурами Python, уже известными вам. Например, используем функцию get_formatted_name()
    в цикле while
    , чтобы поприветствовать пользователей более официально. Первая версия программы, приветствующей пользователей по имени и фамилии, может выглядеть так:
    greeter.py
    def get_formatted_name(first_name, last_name):
    """Возвращает аккуратно отформатированное полное имя."""
    full_name = f"{first_name} {last_name}"
    return full_name.title()
    # Бесконечный цикл!

    Возвращаемое значение 155
    while True:

    print("\nPlease tell me your name:")
    f_name = input("First name: ")
    l_name = input("Last name: ")
    formatted_name = get_formatted_name(f_name, l_name)
    print(f"\nHello, {formatted_name}!")
    В этом примере используется простая версия get_formatted_name()
    , не использую- щая вторые имена. В цикле while
     имя и фамилия пользователя запрашиваются по отдельности.
    Но у этого цикла while есть один недостаток: в нем не определено условие завер- шения. Где следует разместить условие завершения при запросе серии данных?
    Пользователю нужно предоставить возможность выйти из цикла как можно рань- ше, так что в приглашении должен содержаться способ завершения. Команда break позволяет немедленно прервать цикл при запросе любого из компонентов:
    def get_formatted_name(first_name, last_name):
    """Возвращает аккуратно отформатированное полное имя."""
    full_name = f"{first_name} {last_name}"
    return full_name.title()
    while True:
    print("\nPlease tell me your name:")
    print("(enter 'q' at any time to quit)")
    f_name = input("First name: ")
    if f_name == 'q':
    break l_name = input("Last name: ")
    if l_name == 'q':
    break formatted_name = get_formatted_name(f_name, l_name)
    print(f"\nHello, {formatted_name}!")
    В программу добавляется сообщение, которое объясняет пользователю, как за- вершить ввод данных, и при вводе признака завершения в любом из приглашений цикл прерывается. Теперь программа будет приветствовать пользователя до тех пор, пока вместо имени или фамилии не будет введен символ 'q'
    :
    Please tell me your name:
    (enter 'q' at any time to quit)
    First name:
    1   ...   13   14   15   16   17   18   19   20   ...   52


    написать администратору сайта