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

Первым языком программирования, который я действительно выучил, был C в университете. Я даже взял в него необязательный дополнительный модуль. Но после нескольких лет в глуши, только около года назад я в гневе использовал его, когда начал работать с Arduinos. Задача, для которой C подходит больше, чем Python. Однако недавно я начал изучать Python для науки о данных, и вот что я обнаружил:

Примеры цикла for

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

C:

#include <string.h>
    
    char medals[3][7];
    strcpy(medals[0], "Gold");
    strcpy(medals[1], "Silver");
    strcpy(medals[2], "Bronze");
    
    int i;
    for(i=0; i<=2; i++){
        printf("Medal %d is %s \n", i+1, medals[i]);
    }

Питон:

medals = ["Gold", "Silver", "Bronze"]
for i, m in enumerate(medals):
    print(f'Medal {i+1} is {m}')

Что такое слово, как не набор букв?

Я думаю, мы должны начать с самого верха, с того, что, безусловно, имеет наибольшее визуальное значение: создание списка медалей. Взглянув сначала на Python, мы увидим, что мы можем объявить переменную medals как список строк по контексту. Строки, потому что они в кавычках (или апострофах). Перечислите, потому что они в квадратных скобках.

Однако C не имеет строкового типа данных. В C строки — это список (или массив) символов, поэтому список строк — это массив массивов символов. (Вы также заметите, что я включил библиотеку string.h, чтобы упростить ввод слов в массив.)

Но Мэтью, почему вы установили длину массивов символов равной 7, если в самом длинном слове всего 6 букв?
— Рад, что вы спросили. В C слово представляет собой нечто большее, чем просто набор букв: нулевой символ: \0. C использует это, чтобы отметить, где слово заканчивается. (Для эксперимента я изменил длину на 6, и вторая строка получилась такой: Medal 2 is SilverBronze)

Синтаксическое налогообложение

Следующее большое различие в том, как они выглядят, — это синтаксис. Конечно, синтаксис двух языков отличается, но в C его больше. Это делает C для меня просто более неуклюжим кодом. В конце каждой строки нужна точка с запятой. Чтобы сгруппировать строки кода в цикл или функцию, они должны быть заключены в фигурные скобки.
Код Python должен выполнять те же синтаксические функции, но он делает это через структуру. Если не указано иное, конец строки является концом строки. Цикл будет начинаться с двоеточия, но код будет сгруппирован по отступу, который большинство редакторов вставляет автоматически; И хотя C по-прежнему будет работать без отступов, он все же предназначен для удобочитаемости.

Цикл For

Возможно, самым большим изменением, которое я обнаружил, когда пришел в Python, был цикл for. Это просто так чуждо. Я привык объявлять переменную, которую собирался использовать для итерации (i, выше), и мне приходилось все это настраивать: инициализировать переменную начальным номером (i=0); Введите условие, используемое для проверки продолжения цикла (i‹=2); и дайте ему функцию для обновления переменной (i++). Затем я использовал это изменяющееся число для всего, что нужно было повторить.

Питон совсем другой. В Python есть типы с итерируемостью, закодированные в их костях. Чтобы быть итерируемым в Python, тип или класс (определяемый пользователем тип, хотя в наши дни разница незначительна) должен иметь функцию __iter__ и функцию __next__. __iter__ возвращает итератор для объекта, а __next__ возвращает следующий элемент. С этими инструментами нет необходимости создавать внешнюю переменную для повторения. Цикл for Python создает объект итератора для списка medals и пытается получить следующий элемент, назначая его i. Когда он достигает конца и не может получить другой элемент, он вызывает исключение StopIteration, которое обрабатывается путем завершения цикла.

В некоторых случаях вы можете захотеть, чтобы число увеличивалось с итерациями объекта. В C это уже есть для вас, поэтому я счел справедливым показать этот случай на моем примере. Это то, что дает вам функция перечисления Python. Это приводит меня к:

Множественное назначение

Я заметил еще одно непреднамеренно продемонстрированное отличие: слегка затененный пример множественного присваивания. Функция enumerate возвращает два значения: целое число восхождения и соответствующий элемент; и они назначаются i и m — в одной строке! Ближе всего к множественному присваиванию C подходит к присвоению разным переменным одного и того же значения.

Назначение типа:

Взгляните на цикл for в C, посмотрите на i. Простой итератор этого скромного цикла здесь, чтобы выполнить одну работу, прежде чем мы отбросим его в сторону. Даже этот i нуждается в объявлении своего типа, как и любая переменная. В то время как в Python вам не нужно ничего объявлять, вы можете просто присвоить что угодно где угодно. Вы хотите присвоить что-то новой переменной? -Просто сделай это. Это другой тип? -Без проблем.

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

в я

- выделяет кусок памяти, достаточно большой для целого числа, которое мы можем обозначить как i. Переменная C прочна: вы можете пойти и найти ее, манипулировать ею; назначьте его другой переменной (например, int j = i), и вы получите два отдельных фрагмента памяти с одинаковым значением.

Python работает немного по-другому. Переменная python более эфемерна. Конечно, значение существует в памяти, на самом деле тип хранится вместе с ним, но переменная — это просто имя, которое к ней привязывается. Когда вы изменяете значение переменной, новое значение вычисляется, записывается куда-то в память, и переменная переназначается в новый раздел памяти.

Однако бывают случаи, когда вам нужна переменная без значения, чтобы иметь тип. Для этих случаев в Python есть объявление типа, но оно более тонкое и выполняется с помощью синтаксиса:

Словарь = {}

Переменные Python: у вас есть право оставаться необъявленными. Но это может привести к ошибке при запуске, если вы не объявите ничего, чей метод вы позже полагаетесь в коде c̶o̶u̶r̶t̶, э-э….

Ну наконец то

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

P.S.

Однако есть одна вещь, которую кодировать на C быстрее. В цикле C for вы найдете i++, это увеличивает значение i на единицу. Эквивалентом в Python является i +=1, что далеко не так хорошо. Я подозреваю, что это происходит из-за различий в хранении переменных, о которых я упоминал, когда говорил о присвоении типов.