Найти тему
Стив Май

Чем плох пайтон или какой язык программирования лучше изучать в школе?



Этот вопрос очень интересный и очень скользкий. На уроках информатики издревле изучали бэйсик или паскаль. Это если вообще что-то изучали, а не просто рисовали в пэйнте. Однако в последнее время развелось много всяких "простых" и модных языков типа Python или Ruby. Я уж не говорю о всяких курсах робототехники и прочих.

На одном сайте нашёл очень интересное сравнение языков C++ и C# (которое меня и сподвигло на эту статью):
C++ — это язык программирования среднего уровня, более быстрый и близкий к машинному коду. C# — это язык программирования высокого уровня, который легче изучить.

Нам-то как раз интереснее последняя фраза: "который легче изучить"

В околоайтишной сфере каждый кулик своё болото хвалит. Кто-то хвалит питон, кто-то джаву, а кто-то с пеной у рта доказывает, что лучше и проще, чем си шарп не найти. Но если мы спросим нормального программиста, какой язык программирования лучше, тот оветит однозначно: "достали уже с этим вопросом". Почему? Потому что нет "лучшего языка". Для каждой задачи подбирается свой набор инструментов. Если задача состоит в том, чтобы получить максимальное быстродействие аппаратной части, то лучше ассемблера или хотя бы чистого C найти трудно. Если нам нужно быстро автоматизировать какую-то рутинку на компе, то bash или powershell скрипт решит всё как нельзя лучше. А если нужно создать более или менее крупный проект, то используются десятки разных языков и инструментов. Другими словами, нельзя однозначно сказать, какой язык лучше, пока не поставлено чёткое техзадание.

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

Так вот, давайте попробуем подобрать язык программирования под это техзадание.

Сначала нужно кое-что знать о языках программирования, о чём часто забывают учителя в школе. Условно ЯП можно разделить на 4 категории по их уровню (нас интересует именно такая клссификация):
1. Имплементативные - так я для себя называю языки типа ассемблера или фортрана. Программа на таком языке - это линейный список команд, фактически сводящихся к последовательным операторам, условным, циклам и переходам к заданной строке.
2. Функциональные - это языки, в которых процессы представлены как функции в математическом понимании этого слова (это уже общепринятое название).
3. Обектно-ориентированные - языки программирования, реализующие объектную модель данных и методов.
4. Прочие - объединяющая группа языков, реализующих разные, более сложные модели, например, СУБД, нейросети и пр. (они нас интересовать не будут).

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

Сейчас для нас важно, что язык с высоким уровнем абстракции можно приспособить в качестве языка с более низким уровнем абстракции. Например, никто не мешает писать на C++ без его объектной части, что фактически привёдет нас к чистому C, а если в главной функции C делать ассемблерные вставки, то уровень абстракции снизится ещё на один. Условно C++ > C > ASSEMBLER. А вот наоборот не получится (но есть нюансы). Этакая "матрёшка" получается.

Есть и другая сторона медали. Количество строк кода сильно зависит от уровня абстракции.
Общая тенденция: чем выше уровень, тем меньше кода. Программа на пайтоне занимет 3 строки, она же на чистом си занимет 60 строк, а после компиляции в ассемблере она начинает занимать 300 строк.
Есть воторая не менее важная для нас тенденция: Чем выше уровень, тем больше служебных конструкций (накладные расходы). Если в ассемблере мы в первой же строке кода указываем команду, то в си уже нужно хотя бы описать точку входа (функция main), что напрямую к выполняемому алгоритму не относится, а пайтону вовсе требуется внешняя программа-интерпретатор.

Кстати, пайтон занимет в зоопарке языков очень любопытное положение. Это интерпретируемый язык сценариев, реализующий объектную модель. Для нас это означает, что пайтон - не самостоятельный язык (не общего назначения). Обычно он встраивается в прикладные программы для целей автоматизации. Из этого не следует, что на нём нельзя писать полноценные программы, это значит, что пайтон не заточен для написания программ. Сейчас он позиционируется как язык, существенно сокращающий время на разработку. Но цена этого сокращения - очень высокий уровень абстракции. Один из элементов этой абстракции - динамическая типизация, которая стоит на несколько ступеней выше статической типизации из того же Паскаля.

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

В процессе развития, ребёнок осваивает различные уровни абстракции. Более или менее полно абстрактное мышление развивается годам к 13-14 (7-8 классы). В этом возрасте ребёнок уже способен разобраться с понятиями множество, функция, величина. Соответственно, с этого возраста становятся доступны языки программирования высокого уровня. Но. Точно так же, как бессмыссленно разбираться с понятием функции, пока не разобрался с понятием арифметических действий, бессмыссленно изучать ООП (объектно-ориентированное программирование), пока не освоился с функциональным программированием, а оно, в свою очередь, требует умения писать имплементационные (последовательные) программы.

Получается, что раньше, чем в 7 классе вводить изучение ООП бессмыссленно. Ребёнок будет чисто физически не в состоянии разобраться с этим понятием. Не говоря уже о том, чтобы использовать его во взрослой жизни. А это ставит жирнючий крест на таких языках, как пайтон. Да, мы можем во втором классе ввести информатику с программированием на пайтоне. Но это приведёт лишь к тому, что ребёнок, будучи не в силах даже осознать, какой камень он пытается поднять, либо возненавидит программирование, либо тупо выучит все решения всех задач. С этой точки зрения, C++ и C# совершенно одинаково невозможно изучить до 7 класса. При этом "Шарп", как язык существенно высшей абстракции, чем "плюсы", изучить будет сложнее

Для обучения как раз очень важно, использовать минимальные уровни абстракции, чтобы объяснять ребёнку в прямом смысле на пальцах, что происходит внутри машины, когда он запускает свою программу. Абстракция уровня "переменная целого типа" вообще может быть записана на бумаге в клеточку карандашом в любой системе счисления (что очень важно для ЕГЭ, ибо там есть задания с битовыми операциями). Более сложные массивы - неплохо записываются на большой бумаге в клеточку. А как быть с классом "list" из пайтона или с переменными динамического типа из Java? В общем, одним из полезнейших качеств языка программирования для обучения должна быть наглядность.

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

Только после этого можно подходить к абстракциям более высокого уровня. И уж самым последним должно быть "уже сделанное" умными дядями программистами.

Тем не менее, выше я указал, что языки высокого уровня МОЖНО использовать, как языки низкого уровня. С пайтоном это сделать будет чуть труднее, но всё же возможно. Труднее, кстати, не с точки зрения техники (достаточно сделать шаблон из служебных конструкций, см. выше), а с точки зрения психологии (см. пример ниже). Не в последнюю очередь -- психологии учителя.
И наверное, это самый большой гвоздь в крышку гроба пайтона, как языка для обучения. Слишком уж выско соблазн использовать list.sort() вместо 120 строк "си-стайл" кода с косвенной рекурсией и прочими сложностями.

И всё же из этой ситуации есть выход (опять же не в пользу пайтона, но всё же).

Есть один очень эффективный приём обучения программированию (уже на выскоком уровне). Берётся высокоуровневая конструкция языка (например, класс std::string в C++), и обучающийся должен повторить её функционал низкоуровневыми средствами (того же C++). То есть, прямо задача ставится "изобрести велосипед". Но если с классом в "плюсах" всё обстоит просто, и любой, более-менее знакомый с ООП и С++ (школьник старших классов) может без особого труда реализовать этот класс, то в пайтоне для сортировки массива используется алгоритм TIM-SORT, требующий от ученика знания о сортировке частично сортированных больших спискав. Что, согласитесь, для школьника, даже очень продвинутого, слишком круто.
В принципе, этот метод можно адаптировать и для менее сложных вещей и даже для Пайтона. Но он всё равно предполагает некоторый начальный уровень. Который есть далеко не у каждого школьника.

Какой же выбрать язык?
С одной стороны, язык не должен быть слишком выскоуровневым. Он не должен подначивать заменить 5 тем из раздела "типовые алгоритмы" и 3 темы из раздела "рекурсия" одним вызовом уже заранее кем-то написанной функцией.
С другой стороны, изучение километровых листиногов ассемблерного кода, описание регистров, инструкций и вообще, уже само по себе является одной из труднейших задач программирования.
Нужна золотая середина.

И тут мы приходим к интересному выводу.
Более высокая абстракция уменьшает усилия, но при этом скрывает от нас важные вещи. И вот эти важные вещи, менее абстрактные, нужно предварительно изучить на чём-то более примитивном.
Мало ограничиваться одним языком. Для первичного обучения идеальным был бы Паскаль, в котором абстракция сведена к минимуму. Кроме того, там органично используются функции и процедуры, так что первые два уровня программирования (достаточные большинству людей) на нём освоить можно. Единственное, что немного усложняет его использование, это большой объём дополнительных строк кода. А вот ООП и другие абстрактные вещи можно изучать на языках типа C++, где при желании можно заглянуть под капот любого изучаемого класса. Довольно хорошим решением для первичного обучения ООП мне видится Delphi(Visual Pascal) или VisualBasic. Они предлагают весьма наглядную среду, где экземпляры классов представлены в виде конкретных кнопочек и картинок на экране, а их свойства и методы перечисляются в обозримых списках, читать которые можно даже без навыков ООП.

Бонус
Пример учебной ситуации с пайтоном
Перед учеником стоит задача написать программу сортировки массива. Важно: не отсортировать массив, а написать программу (читай: алгоритм) сортировки. Массивы - это довольно низкий уровень абстракции, поэтому задача решаема даже в ассемблерах. Если он будет писать на Бэйсике или на Паскале, ему придётся реализовать что-то типа каноничного пузырька. То же можно написать и на пайтоне -- почему нет? Но ни в одном справочнике по пайтону (а ребёнок вполне может полезть в интернет за подсказкой) нет алгоритма пузырька с его описанием на пайтоне. Зато есть статья "Всё о сортировке в Python: исчерпывающий гайд", в которой написано буквально следующее:
Сортировка в Python выполняется функцией sorted(), если это итерируемые объекты, и методом list.sort(), если это список.
На этом заканчивается основная часть статьи, и идут примеры использования этих методов (реально статья из 17 слов с названием "исчерпывающий").
Разумеется, скопировав из примера программу, ученик сможет отсортировать массив. Но перед ним стояла совершенно другая задача. То есть, учебная задача не выполнена, хотя, задача решена. Важным психологическим моментом тут является то, что в процессе обучения ученик не всегда должен знать об учебной задаче. Он может что-то смутно подозревать (был когда-то мем про "вот тот человек из задачи, который покупает 30 арбузов"), если достаточно наблюдательный, но есть моменты, когда истинная цель должна быть скрыта (об этом по хорошему надо бы полноценную статью написать).
И возникнет некий диссонанс: по учебной задаче он должен получить "2", ибо он как не знал, так и не знает о типовых методах сортировки, а по прикладной задаче "5+", так как не просто выполнил её, а сделал это оптимальным образом. Это очень сильно похоже на ГДЗ. Там точно так же задача решена, ответ верный, а учебная задача не выполнена. Самым неприятным в описанной ситуации является то, что ребёнок использовал ООП, будучи даже не в состоянии понять концепцию ООП. А это уже знаете на что похоже? На магию. Или карго-культ -- кому как нравится больше.