Бран · продюсер «Хроник Пограничья»
Ты посчитал долю платящих за понедельник. За вторник я скопировал ячейку, поменял числа и случайно оставил старый знаменатель. Можно один раз записать расчёт, а потом только передавать данные?
В прошлом уроке ты выбирал строки условиями и складывал числа в цикле. Теперь дадим расчёту имя. Как представление в SQL, функция хранит правило, чтобы не копировать его в каждый отчёт.
Сначала расчёт, потом имя
Запусти эту ячейку целиком:
def percent(part, total):
return part / total * 100
monday = percent(12, 80)
tuesday = percent(9, 60)
print(monday)
print(tuesday)
Она напечатает два раза 15.0. Вызовы передали разные числа, правило осталось одним.
def начинает определение функции. После него стоят имя percent, круглые скобки с именами входных значений и двоеточие. Строки с отступом в четыре пробела составляют тело функции. Они выполнятся не при определении, а при вызове percent(...).
part и total называются параметрами. При первом вызове part получает 12, а total получает 80. При втором они получают 9 и 60.
return возвращает значение в место вызова и сразу заканчивает этот вызов. Поэтому результат можно присвоить переменной, сравнить или передать в другую функцию. Строки без отступа ниже уже стоят снаружи функции.
Позиции и имена аргументов
Следующую ячейку запускай после определения percent:
print(percent(12, 80))
print(percent(part=12, total=80))
print(percent(total=80, part=12))
Все три строки напечатают 15.0. В первом вызове значения распределяются по позиции: сначала part, потом total. Во втором и третьем ты явно указал имена, поэтому их порядок можно поменять.
Знак = внутри вызова задаёт именованный аргумент. Он не создаёт переменную part снаружи. Имена должны совпадать с параметрами определения: percent(paid=12, total=80) не подойдёт, параметра paid нет.
Позиционные аргументы пишут перед именованными: percent(12, total=80) допустимо. Для отчёта percent(part=paid_players, total=active_players) часто легче читать, чем два числа без подписей.
Вернуть не значит напечатать
Отдельная ячейка с другой функцией:
def show_percent(part, total):
print(part / total * 100)
result = show_percent(12, 80)
print(result)
Сначала появится 15.0, затем None. Первая строка пришла из print внутри функции. Но функция ничего не вернула явно, поэтому её результат равен None.
print показывает значение человеку. return отдаёт значение следующему расчёту. Для аналитической функции обычно нужен return, а печать оставляют вызывающей ячейке. Без явного return или с пустым return функция возвращает None.
None обозначает отсутствие значения, не число ноль. С ним нельзя продолжать арифметику как с готовым процентом. Это пригодится, когда метрику нельзя определить.
Пустой знаменатель: не выдумывай ноль
Что такое доля платящих, если активных игроков нет? Деление 0 / 0 не определено. Ноль процентов означал бы другой факт: игроки были, но ни один не платил.
Замени определение percent этой ячейкой и сразу запусти примеры:
def percent(part, total):
if total == 0:
return None
return part / total * 100
print(percent(0, 20))
print(percent(0, 0))
Ответы: 0.0 и None. Ранний return None останавливает вызов до деления. Следующий return стоит на уровне if, а не внутри него: до него доходят только вызовы с ненулевым знаменателем.
Покажи результат честно. Это продолжение предыдущей ячейки:
share = percent(0, 0)
if share is None:
print("Нет активных игроков, доля не определена")
else:
print(share)
is None проверяет отсутствие значения. Не пиши if not share: и None, и 0.0 считаются ложными, а причины у них разные.
урок из курса
Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.