Поделюсь с вами одной из моих любимых аналогий.

Я раньше сам молол себе кофе. Купил такую старомодную ручную кофемолку с металлической воронкой, крутильной рукояткой и маленьким деревянным подносом, на который ссыпается смолотый кофе.

Может быть, где-то у меня она ещё валяется.

Теперь я слишком занят. Перешёл на кофемашину. Она из таких, которые заправляются капсулами – то есть, максимально потворствует лени, а значит, работает максимально эффективно. Привожу этот пример на лекциях по программированию для начинающих – когда объясняю, что при работе над кодом леность – это хорошо, она свидетельствует об эффективности.

В этой статье речь пойдёт именно о такой кофемашине. Не о самом кофе, поэтому я обойдусь без избитых шуток вроде «программист – это человек, преобразующий кофеин в код».

Но ещё эта статья рассказывает о функциях Python. Она в основном о функциях Python.

Так что можете налить себе чашечку кофе — а, кажется, я обещал обойтись без глупых шуток? Извините! – и присаживайтесь поудобнее, слушайте. Возможно, в итоге у вас в голове сварится парочка свежих озарений о том, что можно сделать с функциями на Python – по капельке, по глоточку. [Стивен, стоп!]

Кофемашина. Функция


У кофемашины есть назначение – или, если хотите, функция. Здесь я буду использовать слово «функция» именно в таком общеупотребительном значении.

Причём, у кофемашины есть ровно одна функция — варить кофе.

Прежде, чем выпить вкусного кофе, вы должны предоставить кофемашине некоторые ресурсы, а именно:
  • Воду
  • Электричество
  • Кофе (допустим, в таблетках, именно такая у меня машина)

Добавляете три этих ингредиента и нажимаете ON. Только не забудьте поставить под носик чашку или кружку.

В машине что-то происходит. Вас не особенно интересует, что именно. Вам нужно только чёрное золото, льющееся вам в чашку. Мммм вкусно.

Вы только что вызвали функцию. Кофемашина — это функция. Сейчас я употребил слово «функция» именно в том значении, которое знакомо программистам.

Вы передаёте кофемашинной функции воду, электричество и кофе в качестве аргументов. Вы вызываете функцию, когда нажимаете кнопку ON, и кофемашина возвращает жидкий кофе вам в чашку.

Но давайте разовьём эту аналогию. Здесь ещё много что можно исследовать.

Вы сами собрали себе кофемашину?


Вы купили кофемашину, распаковали её, но начинается её существование не с этого.

Кто-то когда-то собрал эту кофемашину. Инженер её спроектировал, предусмотрел, что будет у неё внутри, и как различные её элементы будут взаимодействовать друг с другом. В данном случае спроектировать и собрать кофемашину — всё равно, что определить функцию в Python:

image

Но, подбирая названия для функций в Python, лучше именовать их исходя из того, что они делают, а не что собой представляют. Так что давайте переименуем эту функцию:

image

Она по-прежнему представляет кофемашину. Но теперь мы чётко артикулируем, что нас интересует акт приготовления кофе, а не сама машина — так и должно быть!

Дорогой читатель, если вы – не мастер по ремонту кофемашин, то, вероятно, вы и не знаете, как кофемашина работает, и вас это не интересует. Налил воды, заправил кофейную таблетку, включил машину в розетку. Потом нажал кнопку — и ваш кофе готовится.

Одно дело — определять функцию, а другое — вызывать её.

Именно здесь вам и пригодится инструкция к кофемашине. В случае с функцией такую роль может играть строка docstring или страница с документацией. Здесь аналогия тоже удачная. Многие пользователи не читают инструкций — и документацию к коду обычно тоже никто не читает!

В инструкции к кофемашине немного подробнее описано, как следует пользоваться этой функцией. Чтобы кофемашина работала, вы должны предоставить её три вещи:

image

Кроме того, эта инструкция сообщает, что готовый продукт кофемашины — это заварной кофе. Надеюсь, это действительно так!

Итак:
  • Если вы мастер по кофемашинам, то должны знать, что записать в определение функции. Это текст def make_coffee():
  • Если вы просто хотите чашку кофе, то вам достаточно знать, как обращаться с кофемашиной. Вы должны вызвать make_coffee().

Когда пишешь код, вызывать функции приходится чаще, чем определять. А если вы как я, то не представляете, что находится внутри большинства из тех функций, что вы вызываете. Знаете, как выглядит код, заключённый в def print():? Я тоже не знаю…

Не приходится задумываться об определениях функций, если вы знаете, что делают эти функции, и как их использовать.

Но зачастую, когда вы пишете код, вы выступаете в роли инженера, конструирующего кофемашины. Вам приходится определять функции. Определения функций – мощный инструмент, необходимый каждому программисту для эффективной работы.

Как сделать чашку кофе


Хорошо. У вас есть кофемашина, и вы прочитали инструкцию. Вы готовы этой машиной пользоваться.

У нас в определении функции три параметра: water, electricity и coffee. Эти параметры стоят на месте тех составляющих, которые понадобятся вам для работы.

Параметр water обозначает встроенную в кофемашину ёмкость с водой. Туда наливают воду.
Шнур с вилкой, выходящий из задней стенки машины, называется electricity. Как вы уже догадались, та ячейка, в которую закладывается кофейная таблетка, называется coffee.

Но, пользуясь кофемашиной, вы сами должны обеспечить её водой, электричеством и кофейными таблетками. То есть, передать аргументы функции. Эти аргументы сохраняются при помощи имён параметров.

Давайте вызовем функцию make_coffee():

image

Тогда как имена параметров water, electricity и coffee — это просто метки, используемые при определении функции, аргументы tap_water, electricity_from_wall_socket и blue_espresso_intenso_pod — это конкретные сущности, которые вы применяете при вызове функции, то есть, когда включаете кофемашину.

Можно передавать функции и другие вещи. Например, вы можете обзавестись фильтрами для воды, в таком случае передаёте filtered_water в качестве первого аргумента. Может быть, у вас сейчас проблемы с водопроводом — в таком случае, можно передать bottled_water (бутилированную воду). А вот проточной водой sparkling_water лучше не пользоваться!

А что, если у вас есть электровелосипед, который в стационарном виде может работать в качестве генератора электричества? В таком случае можно передать вторым аргументом electricity_from_stationary_bike, поэтому за каждой варкой кофе вы заодно успеете неплохо размяться.

Не любите эспрессо? Тогда попробуйте caramel_pumpkin_spice_vanilla_latte_pod(кстати, кто-нибудь пил такое?)

Можно передать любой аргумент, если это аргумент подходящего типа. В предыдущем предложении слово «тип» — это не термин. В языке Python применяется утиная типизация, поэтому в данном случае важен не сам тип, а его релевантные характеристики.

Например, в качестве первого аргумента можно передать кофемашине любую неядовитую жидкость, которая бы не разъела ёмкость. Можно. Но не значит, что следует.

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

Включаем машину


На кофемашине есть кнопка ON. Чтобы машина заработала, её нужно нажать. Думаю, это понятно и без инструкции по применению.

Что служит кнопкой ON в функции Python? Это скобки, которые вы добавляете вслед за именем функции, выполняющей эту задачу.

Напомню, что функция make_coffee представляет кофемашину. Как я уже говорил, в данном примере мы вполне могли бы назвать эту функцию coffee_machine, но назвали make_coffee в соответствии с наилучшими практиками именования.

В коде Python есть существенная разница между make_coffee и make_coffee(). Первый вариант, make_coffee – это имя функции. Оно относится к кофемашине как таковой. Рассмотрим следующую строку на Python:

image

Приведу ещё одну аналогию, которой часто пользуюсь. Оператор присваивания описывает, как вы присваиваете объект переменной с некоторым именем, ставя между ними знак равенства. В таком случае вы как будто кладёте объект Python в коробку. В данном случае коробка называется output. Что же попадает в эту коробку?

Вся кофемашина!


Поскольку make_coffee обозначает кофемашину, вы храните всю кофемашину в коробке output. Функция в Python является объектом. Следовательно, функция хранится в переменной output.

Теперь рассмотрим следующую строку:

image

Да, вы правы! Это не сработает. Но наберитесь терпения и дочитайте абзац. Скобки в данной функции работают как кнопка ON. Вы включили кофемашину, но забыли о трёх важных вещах. Во-первых, в ёмкости нет воды. Из-за этого можно было бы повредить машину, но, вдобавок, вы и не включили её в розетку, поэтому совсем ничего не произойдёт.

Читаете инструкцию. Выясняете, что необходимо передать три аргумента. Что ж, попробуем ещё раз:

image

Скобки на месте. Следовательно, вы включаете машину, но на этот раз вы также позаботились о воде и электричестве, а также заправили в машину кофейную таблетку.

Машина начинает тарахтеть и урчать, после чего возвращает горячий жидкий кофе, который…

…хранится в чашке под названием output. То есть, возвращаемое значение сохраняется в переменной output.

Не забудьте о чашке


Если хотите сохранить возвращаемое значение – не забудьте присвоить его переменной. Рассмотрим следующий код:

image

Вы вызываете функцию. Скобки на месте. Все три аргумента правильные.

Кофемашина начинает ворчать. Уже через полсекунды чувствуется аромат кофе. Буквально. Кофе течёт…

…прямо в сток в нижней панели машины. Вы забыли подставить чашку под носик. Кстати, и я на этой неделе тоже так прокололся – совершенно очевидно, потому что мне требуется чашечка кофе!

Если только вы не собирались скрючиться, подставить рот под носик и таким образом выпить порцию кофе – не рекомендую так делать – то с тем же успехом кофе можно было бы вылить в раковину.

Вот почему необходимо присваивать возвращаемое значение переменной. На этот раз давайте назовём переменную cup:

image

Может быть, у вас есть и другая функция, drink_beverage(). Логично предположить, что и этой функции требуется аргумент – безалкогольный напиток. Поэтому вы могли бы вызвать drink_beverage(cup).

Но можно вызвать функцию и вот так:

image

Вы вызываете make_coffee() прямо внутри скобок функции drink_beverage(). Когда make_coffee() возвращает значение, оно поступает прямо в drink_beverage() в качестве её аргумента.
Да, это как раз тот сценарий, когда вы подсовываете рот прямо под носик кофемашины.

Внимание: так вы определённо ошпарите себе рот!

Допиваем


Мне нравится аналогия с кофемашиной. Она идеально соответствует законам аналогий от Стивена. Вот эти законы:
  1. Аналогия должна выстраиваться на основе будничного сценария, который понятен любому без всякого интеллектуального напряжения.
  2. Компоненты аналогии и те концепции, которые она описывает, должны максимально точно соответствовать друг другу.

Любой из нас видел кофемашину в действии – значит, первое условие выполняется. А эта статья, надеюсь, убедила вас, что данная аналогия очень хорошо описывает основы работы с функциями – соответственно, и второе условие можно отметить галочкой.

Кроме того, для этой аналогии, как и для любых других, верно одно правило: все аналогии на каком-то этапе перестают работать. Поэтому на примере кофемашин невозможно объяснить все тонкости работы с функциями в Python. Поэтому налейте кофе и почитайте об этом в книге!

image

Комментарии (8)


  1. DmKazakov
    04.10.2024 14:30
    +2

    Агонь! Забрал себе и буду ссылаться на уважаемого автора)


  1. IvanZaycev0717
    04.10.2024 14:30

    я обойдусь без избитых шуток вроде «программист – это человек, преобразующий кофеин в код»

    такой программист долго не протянет. Психостимуляторы типа кофеина могут показаться хорошей идеей пока у вас не возникнут проблемы со здоровьем из-за этого


  1. Doc_69
    04.10.2024 14:30
    +2

    Да круто объяснил, неплохая памятка


  1. rukhi7
    04.10.2024 14:30
    +2

    Если это памятка для школьников то ничего так, нормально.

    Если это памятка для проженных гуманитариев, вроде тоже хорошо.

    Если это памятка для инженеров, которые как бы должны были уже получить высшее техническое образование то не знаю что и сказать. Наверно как-то глупавато, что ли.


    1. anonymous
      04.10.2024 14:30

      НЛО прилетело и опубликовало эту надпись здесь


    1. Elemental4096
      04.10.2024 14:30

      Если забыть правило Хабра. Писать подробно и понятно. Эта статья отлично описывает одну тему. Если она одна, она не будет высокоэффективна. Но если из таких статей собрать пособие по программирование на Змее, оно будет крайне полезным и понятным. (Хочешь указать на преимущества, укажи. Хочешь указать, на проблемы, подумай, стоит ли оно того, и указывай неагрессивно и с предложениями по улучшению.)


  1. sevmax
    04.10.2024 14:30
    +1

    Отлично описано, простые аналогии для начинающих!

    Пара поправок в английских терминах:

    • tap_water - это проточная вода

    • sparkling_water - это газированная вода


  1. Kerman
    04.10.2024 14:30

    Странная логика. Ведётся обсуждение, что имя метода надо называть make_coffee, а не coffee_machine. И не объясняется, почему. Просто потому что "так принято".

    Тем временем, пайтон - вполне себе объектно-ориентированный язык.

    Вот смотрите: моя кофемашина не требует подачи электричества, воды и кофе на каждый вызов "делайкофе". Я один раз включаю в розетку, один раз с утра заливаю воду, один раз засыпаю кофе. Потом хожу, нажимаю кнопку - только успевай чашку подставлять.

    Можно же было сделать класс coffee_machine, передать ему кофе и воду и воткнуть в розетку? А make_coffee будет уже без аргуменов. Тогда почему наименование класса - это существительное, а имя метода - глагол становится понятнее, правда?

    Ещё можно кидаться эксепшенами, если запас кофе или воды в машинке закончился, но это уже другая история.

    p.s. sparkling water - это газированная вода, а не проточная.