HRP-N3 - серия источников питания с максимальной пиковой мощностью в 350% от MEAN WELL
РадиоЛоцман - Все об электронике

Python лучше C! (Или все-таки наоборот?)

Журнал РАДИОЛОЦМАН, октябрь 2016

Max Maxfield

embedded.com

Если вы введете в поисковик Google что-нибудь вроде «Python vs. C», то найдете множество сравнений этих языков. К сожалению, понять, какой же из них «лучше», почти невозможно по многим причинам, и не в последнюю очередь из-за того, что чрезвычайно трудно определить, что подразумевается под «лучшим».

Одним из аспектов всего этого является то, что в сети не так уж часто встречаются дискуссии, в которых языки Python и C сравниваются в контексте встраиваемых систем, особенно приложений на основе малых микроконтроллеров для «вещей», предназначенных для подключения к Интернету вещей. Так что, я готов порассуждать здесь об этом, но сначала…

… интересно отметить, что сегодня существуют буквально сотни и сотни различных языков программирования. Если вы посмотрите, например, в Wikipedia, то найдете 54 языка, названия которых начинаются с буквы «A» (я уж не говорю о тех, которые начинаются с «C» или «P»), и этот список даже не включает в себя более эзотерические языки, такие как Whitespace, в котором используются только пробельные символы (пробелы, табуляции и возврат), и игнорируются все другие, но мы отвлеклись…

Причина, по которой я затеял здесь эту пустую болтовню, заключается в том, что я только-только закончил чтение блестящей книги под названием «Учимся программировать с Minecraft» (Learn to Program with Minecraft) автора Крейга Ричардсона (Craig Richardson). Акцент в этой книге сделан на обучении языку программирования Python; в ней предлагается наиболее удобный, интуитивно понятный и новаторский подход, который я когда-либо видел для любого языка.

В своем обзоре книги я, в частности, сказал: «Я не хочу блуждать в этих дебрях, обсуждая здесь плюсы и минусы таких языков, как C и Python – это заслуживает отдельной статьи». И я был не слишком удивлен, обнаружив, что был прав на 100%, поскольку это действительно отдельная статья.

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

Кто-то мог бы сказать: «Язык является статически типизированным, если типы любых переменных известны во время компиляции, а динамически типизирован тот язык, в котором типы любых переменных интерпретируются во время выполнения». В то же время, в консалтинговой компании Cunningham & Cunningham, скажут, что на самом деле статическая типизация означает, что «…значение явно (что не то же самое, как во время компиляции) ограничено в отношении типа значения, которое оно может обозначать, и что реализации языка, будь то компилятор или интерпретатор, навязывают и используют эти ограничения в максимально возможной степени». Что ж, я рад, что мы прояснили этот момент.

Другое сравнение, которое мы часто слышим, заключается в том, что язык C слабо типизирован, в то время как Python сильно типизирован. На самом деле, заниматься сравнением слабой типизации с сильной можно еще дольше, чем рассуждать о булевой категоризации. Если вы, например, прочитали достаточно статей, то увидите, что C описывается как слабо и сильно типизированный, в зависимости от точки зрения автора. Кроме того, если вы принимаете определение сильной типизации как «Тип значения не меняется внезапно», то как объясните тот факт, что в Python можно сделать следующее:

bob = 6
bob = 6.5
bob = "My name is Bob"

На самом деле, говоря «строго типизированный», мы имеем ввиду, что строка, содержащая только цифры (вроде «123456») не сможет волшебным образом превратиться в число без выполнения нами явной операции (в отличие от Perl, например). В случае приведенного выше фрагмента кода, все, что мы говорим – это то, что переменная bob может иметь различные типы в разные моменты времени. Если бы мы использовали метод type(bob) после bob = 6, то было бы возвращено int (целое число), после bob = 6.5 вернется float (число с плавающей точкой), а после bob = "My name is Bob" будет возвращено str (строка).

Одно, с чем можем согласиться мы все – это то, что C, в отличие от Python, не заставит вас использовать отступы. Это еще одна тема, которую люди могут увлеченно обсуждать, но лично я думаю, что мы можем суммировать все, сказав, что (а) если вы попытаетесь, вы сможете написать невероятно запутанный код на C (существует даже международный конкурс по написанию самого запутанного кода на языке C), и (б) Python заставляет вас использовать отступы, что вы должны делать в любом случае, и в этом не может быть ничего плохого.

Еще один момент, с которым мы все готовы согласиться, касается того, что код на языке C компилируется, а код на Python интерпретируется (давайте не будем здесь погружаться в дебри обсуждения компиляции «на лету»). С одной стороны, это означает, что программа, написанная на Python, как правило, работает медленнее, чем эквивалентная программа на языке C, но это не вся история, потому что во многих случаях в такой программе не будет взаимосвязи между скоростью и производительностью. Это особенно верно в случае приложений, работающих на малых микроконтроллерах, например, таких, которые используются в «вещевой» части Интернета вещей.

Я чувствую, что уже загнал себя в угол тем, что написал, так что давайте пойдем до конца и обсудим несколько примеров, которые показывают, что я думаю об этих вещах, и что думают о них другие люди. Давайте начнем с того, что я думаю о том, что происходило до эпохи Python – примерно в конце 1980-х и начале 1990-х. В то время я был склонен визуализировать программный пейзаж каким-то таким образом (Рисунок 1).

Python лучше C! (Или все-таки наоборот?)
Рисунок 1. Так я думал примерно в 1990-м году.

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

Теперь давайте вернемся в наше время и обсудим, что я думаю о том, как люди воспринимают сегодняшнее положении дел с языками Python и C. Очевидно, процессоры стали больше и быстрее, плюс мы имеем многоядерные процессоры, но здесь мы составим общую картину. В рамках этого мы могли бы заметить, что, по большому счету, сегодня ассемблер используется лишь в малых микроконтроллерах с крохотными объемами памяти (Рисунок 2).

Python лучше C! (Или все-таки наоборот?)
Рисунок 2. Как, по моему мнению, люди думают о языках программирования в 2016 году.

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

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

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

В случае с беспроводным стеком ZigBee, написанным на C, где любые приложения, как правило, будут также написаны на C, сам стек может занимать порядка 100 КБ Flash-памяти, а затем вы должны будете рассмотреть вопрос о дополнительной памяти, необходимой для приложения (более сложным приложениям понадобятся более дорогие микроконтроллеры с памятью 256 КБ). Кроме того, скорее всего вам придется скомпилировать стек на основе C в сочетании с вашим приложением, также на основе C, в один исполняемый файл, который затем нужно будет загрузить в ваш узел беспроводной связи. Помимо этого, придется перекомпилировать ваше приложение со стеком для каждого целевого микроконтроллера.

Для сравнения, стек компании Synapse, который, как и ZigBee, находится на вершине физического уровня и уровня управления доступом к среде стандарта IEEE 802.15.4, требует лишь порядка 55 КБ flash-памяти, включая виртуальную машину Python. Это означает, что если вы решили использовать недорогой микроконтроллер с объемом памяти 128 КБ, то для приложений на основе Python у вас останется 73 КБ памяти.

И эти приложения на основе Python интерпретируются в байткод, выполняемый на виртуальной машине Python. Поскольку каждый байткод формируется из 1 до 10 машинных кодов – давайте возьмем среднее значение 5, – это значит, что 73 КБ памяти вашего приложения на самом деле эквивалентны 73 × 5 = 365 КБ. Кроме того, то же самое приложение с байткодом будет работать на любом целевом микроконтроллере, использующем стек Synapse.

Продолжая свои размышления, я также поинтересовался у моего друга Дэвида Юинга (David Ewing), что он думает о дискуссии «C против Python». Дэвид работает техническим директором Synapse Wireless и, в отличие от вашего покорного слуги, является опытным программистом. Дэвид ответил следующим образом:

C и Python – это фантастические языки, и я люблю их одинаково сильно. Между ними есть, конечно, многочисленные технические, синтаксические и семантические различия – статичность и динамичность, типизация, компиляция и интерпретация, – но суть всего этого заключается в следующем:

  • С является компилирующим языком, более «близким к железу». Это «универсальный ассемблер». Он чист и элегантен. Моя любимая цитата из книги K&R 30-летней давности: «C не является большим языком, и его нельзя хорошо описать большой книгой».
     
  • Python с его «динамической типизацией» и прочими особенностями снижает риск появления «ненужных сложностей». Python интерпретируется (или компилируется «на лету»), поэтому у вас могут быть глупые ошибки, которые не будут обнаружены до момента исполнения. Тем не менее, компиляторы не всегда выявляют серьезные нетривиальные ошибки. В таких случаях поможет только тестирование; решение должно быть тщательно протестировано, независимо от языка реализации.

Дэвид продолжал:

Если проблема может быть решена на Python, то она также может быть решена и на C; но обратное не всегда верно. Однако если проблема может быть решена на Python, то:

  • Решение (исходный код) будет проще, чем соответствующий код на C.
  • Код будет более «читаемым».
  • Возможно, еще важнее, что он будет более легок в написании (это качество часто упускается из виду!).

Благодаря отмеченным выше качествам, решение будет иметь меньше ошибок, и его можно будет гораздо быстрее разработать. И это реальные аргументы в пользу выбора Python вместо C для многих задач.

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

Итак, какой же язык лучше всего подходит для встраиваемых приложений? Я затрудняюсь с ответом. В значительной степени это зависит от того, что вы хотите (должны) получить от своих приложений. Что я скажу дальше, вы знаете, не так ли? Что вы думаете обо всем этом? Какой из этих двух языков вы предпочитаете (а) в общем, и (б) для встраиваемых приложений? Кроме того, если бы мы расширили сферу, то есть ли какой-нибудь другой язык, который вы предпочли бы использовать в мире встраиваемых систем?

Перевод: Mikhail R по заказу РадиоЛоцман

На английском языке: Python is better than C! (Or is it the other way round?)

Электронные компоненты. Бесплатная доставка по России
Для комментирования материалов с сайта и получения полного доступа к нашему форуму Вам необходимо зарегистрироваться.
Имя
Фрагменты обсуждения:Полный вариант обсуждения »
  • Вроде как, статья началась нормально, но последние абзацы испортили всё. Всё, в очередной раз, скатилось к убогим передёргиваниям цифр: "В случае с беспроводным стеком ZigBee, написанным на C, где любые приложения, как правило, будут также написаны на C, сам стек может занимать порядка 100 КБ Flash-памяти, а затем вы должны будете рассмотреть вопрос о дополнительной памяти, необходимой для приложения. ". "Для сравнения, стек компании Synapse, который, как и ZigBee, находится на вершине физического уровня и уровня управления доступом к среде стандарта IEEE 802.15.4, требует лишь порядка 55 КБ flash-памяти, включая виртуальную машину Python. Поскольку каждый байткод формируется из 1 до 10 машинных кодов – давайте возьмем среднее значение 5, – это значит, что 73 КБ памяти вашего приложения на самом деле эквивалентны 73 ***215; 5 = 365 КБ". Т.е, автор пытается этим сказать, что реализация стека на голом Си, занимает в разы больше, чем.. реализация стека + виртуальной машины?( и это без учёта иного ). Или, автор "совершенно случайно", говорит о.. разных протоколах и реализациях и всерьёз их, кагбэ, сравнивает наравне?)) Так же, не раскрыты требования к ОЗУ. Ну и по поводу "плюсов" питона - тож оч большой вопрос..
  • ну как бы СИ и ПИТОН между собой не корректно сравнивать. все таки питон -объектно ориентированный язык, со всеми вытекающими, а си ближе к машинному коду.вот яву и питон более уместно сравнивать.... и потом - си лет на 10 раньше появился нежели питон. и питон частично использует готовые модули написанные на си....