Python: Вызов функций в аргументах функций
Продолжаем тему выражений. Как вы помните, вызов функции — выражение, а значит мы можем положить вызов функции в вызов функции (…в вызов функции в вызов функции в вызов… а-а-а!).
number = -100.234203
result = round(abs(number), 2) # 100.23
Мы вызываем функцию round()
и передаем ей два аргумента:
- результат вызова функции
abs()
с аргументомnumber
- число
2
.
Можно сделать то же самое, но с промежуточными шагами:
number = -100.234203
module = abs(number) # 100.234203
result = round(module, 2) # 100.23
Какой вариант предпочтительнее? Если вычисление совсем простое и неглубокое (не больше одного вложения функции), то можно смело вкладывать вызов в вызов. В остальных ситуациях предпочтительно разбивать вызовы на промежуточные вычисления.
Причины все те же. Чтение такого кода значительно легче. Во-первых, промежуточные переменные своими названиями отражают суть операций. Во-вторых, такой код легче отлаживать, а промежуточные данные проще исследовать. И в-третьих, глубокие вложенные вызовы сложно читать. В продвинутых языках подобная проблема решается механизмом типа композиции функций, но в Python, к сожалению, подобного нет.
Давайте взглянем на код и попробуем ответить на вопрос: что в каком порядке будет вычисляться?
number = -100.234203
result = round(abs(number), round(2.43))
Python, как и большинство традиционных языков, является языком с энергичными вычислениями (в других языках бывают ленивые вычисления). Python пытается вычислить сначала максимально глубокий уровень вызова, затем менее глубокий, и так двигается снизу вверх пока не вычислит всё.
В нашем примере сначала будут вычислены аргументы, а затем получившиеся данные попадут в вызов round()
.
Ситуация с вложенными вызовами функций часто вводит новичков в ступор. Здесь нет никакой магии, нужно просто чуть больше тренировок. Хорошее упражнение — расписывать процесс по шагам на бумажке, симулируя действия компьютера. Вот так:
result = round(abs(number), round(2.43))
result = round(100.234203, round(2.43))
result = round(100.234203, 2)
result = 100.23
Задание
Для построения генеалогического дерева семьи Старков Сэм написал функцию parent_for()
, которая возвращает имя родителя, если передать ей первым параметром имя ребенка. Вторым параметром функция принимает строчку 'father'
или 'mother'
. Так функция понимает, кого из родителей возвращать. По умолчанию параметр равен 'mother'
. То есть, если нужно узнать имя матери, то можно не передавать специально 'mother'
, а передать лишь один параметр — имя ребенка.
Напишите программу, которая выводит на экран имя деда Джоффри по материнской линии. Полное имя Джоффри на английском: Joffrey Baratheon.
Пример использования функции parent_for()
:
mother = parent_for('Joffrey Baratheon')
print(mother) # => Cersei Lannister