Pull to refresh

Comments 79

UFO landed and left these words here

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

UFO landed and left these words here

Вам повезло с интеллектуальным окружением, значит ;-)

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


На мой взгляд, объяснять циклы вместе с массивами — намного сложнее, чем все это по-отдельности. Для людей может быть проблемой осознание самой концепции массивов, индексации, отличия элемента от индекса, а тут вы еще накидываете другие концепции.


По методике преподавания циклов я уже писал статью: https://habr.com/ru/post/456500/
По методике массивов не писал, но очень хочется. Например я заметил, что в начале объяснения массивов вообще не нужно использовать циклы. Это не помогает.
Нужно сначала научить людей наполнять и выводить произвольные элементы из массива. Отдельными неповторящимися действиями, а уже потом добавлять "вот теперь мы должны заставить компьютер повторять рутину за нас".
Еще полезно рисовать трассировочные таблицы, по которым видно как данные перекладываются с места на место.

Добрый день! У Вас, вроде, неплохая статья, довольно интересно, как можно с самых азов объяснить что-то, кажущееся совсем простым, людям, не понимающим это. Правда, интересна последовательность мыслей.
Но Вы немножечко ошиблись целевой аудиторией, как по мне. На Хабре, скорее всего, нет или очень мало людей, не понимающих циклы… и маловероятно, что им будет приятно рассусоливание простейших вещей...


Если бы Вы написали статью с идеей: «Как объяснить школьнику простейшие вещи?» было бы приятнее читать, ведь так нет ощущения поучения.


Но это просто совет насчет статьи и ее преподнесения (и еще код лучше в ячейках писать, а не в скриншотах, так читабельнее).


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

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

На хабре полно разных людей. Не надо всех под одну гребенку грести.
Почему вы не пишете такие комментарии в статьях про политику, Илона Маска или про крем от облысения?

… ну и зачем вам индекс элемента в массиве в финальном коде? А если подумать еще немного, то зачем вам append там же, учитывая, что есть list comprehensions?


Ваше объяснение теряет самую важную деталь: результат — это исходная последовательность, для каждого элемента которой выполнена операция. Для каждого.


PS Зачем вы два раза делаете один и тот же split?

Не хочу обидеть или задеть автора, но сразу вспомнил про тех программистов, которые любят писать сложный(а может и не сложный) алгоритм в одну строчку, у которого читаемость 0. Я там такие конструкции тоже часто видел, просто для того, что бы «лишние переменные» не занимали аж целую дополнительную строчку кода. Надеюсь, автор просто сделал это, что бы читателям было легче вникнуть в суть.

Не применительно к автору, но ещё описанные вами персонажи любят топить за то, чтобы начинать учить программированию с Питона, а не с Паскаля — при том, что Питон дико провоцирует начать забивать гвозди микроскопом и удалять зубы через анус. ИЧСХ, на нём это вполне органично получается делать, но вот новички при виде таких конструкций натурально впадают в ступор.
UFO landed and left these words here

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

UFO landed and left these words here

Можно и, гм, кое-что сдуру сломать, но это уже крайности какие-то.

UFO landed and left these words here
не напоминает. Совсем. Однострочники на perl'е тем и примечательны, что в них ничего не понятно для не perl программистов. В этом примере понятно всё(даже мне, незнакомому с питоном). Код намного более наглядный чем предложенный в статье.
UFO landed and left these words here

Несмотря на то, что list comprehensions юзаю и читаю часто, я с вами соглашусь, что map и лямбды куда нагляднее. Применительно к питону


  • в питоне лямбда функции имею ужасающий синтаксис: lambda x: x
  • list comprehensions быстрее, чем map
  • в list comprehensions есть if, который на map'ах уже не так красиво делается. Тут нужно что-то типо filter
Молодой человек, ну это же котлин, к чему эти индексы)
celebrities.map { it.split(" ").joinToString("") { item -> item.first() + "." } }
UFO landed and left these words here
согласен, тут есть свои проблемы. Но код читается без особых усилий, и сравнение с perl'овскими однострочниками считаю некорректным.

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


А я как-то разбирал за предшественником такое:


variation_flags += [variation_flag for variation in module.variations
        for variation_flag in variation]

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

А что тут непонятного (кроме порядка в каком читать — но программист на Питоне его знать должен)?


Обычная операция flatten над списком списков.

А что тут непонятного (кроме порядка в каком читать — но программист на Питоне его знать должен)?

Ну вот сейчас таки после отправки комментария посидел и показалось, что понял :)
Про порядок — таки это первый случай за весь опыт, когда такое встретилось (причём без особой надобности).
Уверен, что >90% питонщиков тоже это не поймут — ибо нужно чуть реже, чем никогда.

Уверен, что >90% питонщиков тоже это не поймут — ибо нужно чуть реже, чем никогда.

Ну, я прочитал и понял. А я даже питонщик-то ненастоящий. Ну да, я с порядком множественных for в list comprehensions один раз столкнулся в первый год, что ли, ну и запомнил. А у вас он еще и из переменных нормально выводится.

UFO landed and left these words here
UFO landed and left these words here
UFO landed and left these words here
UFO landed and left these words here
Я с языком Х не знаком, вот то ли дело язык Y. Там все сразу лучше и понятнее в N раз
Не печалься, любитель вертикального кода.
def initials(full_name: str) -> str:
    name, surname = full_name.split()
    return f"{name[0]}.{surname[0]}."

map(initials, celebrities)

Несмотря на то, что код выше вполне удобочитаем, этот уж намного легче для понимания.
UFO landed and left these words here
А пруфы производительности то будут? или выдумал?
from timeit import timeit
celebrities = ["Tom Cruise", "Linus Torvalds", "Simon Marlow"]*1000

def initials(full_name: str) -> str:
    name, surname = full_name.split()
    return f"{name[0]}.{surname[0]}."


def f1():
    ["".join(f"{item[0]}." for item in celebrity.split()) for celebrity in celebrities]

def f2():
    tuple(map(initials, celebrities))

print(timeit("f1()", globals=globals(), number=100))
print(timeit("f2()", globals=globals(), number=100))

Python 3.9.1
0.161286
0.067485
На самом деле хорошие тесты сложно провести, которые бы показали насколько код реально хорош. Вспоминается видео на ютубе, где приводили ситуацию, когда код на асинхронной версии работал медленнее чем на последовательной и наоборот. Так что в данной ситуации это может быть и быстрее, но кто знает что будет в других ситуациях.
UFO landed and left these words here
А ты ловкий )
1) Делаем заявление о том, что реализация №2 в 3 раза медленнее реализации №1 потому что «генераторы»
2) Чтобы это доказать переписываем реализацию №2 на свою реализацию №3
3) Доказываем что реализация №1 и №3 выполняются за одинаковое время

4) Справедливость восстановлена
UFO landed and left these words here
UFO landed and left these words here
Исходный однострочник прекрасен, нет слов. И всё же заметьте, что в авторской постановке задачи, как и в авторском тестовом наборе, о сложносочинённых инициалах речи нет. Иногда это важно.
Мне показалось, вы интересовались скоростью решения. Надо полагать, более не интересуетесь. Ну и ладно.
А всё же согласитесь, моё решение еще и читабельно.
UFO landed and left these words here

Привет любителям функциональщины :D
Общее у однострочников на любом языке — они write only. Вносить изменения практически невозможно. Вот, допустим, правило формирования инициалов поменялось (Джером К. Джером, например, попадется в списке). Код с традиционным циклом исправит любой школьник. Ваш вариант — тоже. Однострочник — сделать, конечно, можно, но понять, что это, сможет не каждый.

Генераторы — не лучший способ объяснять циклы.
ИМХО, достаточно убрать лишнее:

celebreties = ['Tom Cruise', 'Will Smith']
shortnames = []
for person in celebreties:
person = person.split()
shortname = person[0][0] + '.' + person[1][0] + '.'
shortnames.append(shortname)

print(shortnames)

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

Автор ordovic, дополни плз. статью реальным кодом — сделаем сравнение по быстродействию с предложенным тобой вариантом / списковым включением / map'ом.

А зачем вам сравнение по быстродействию для учебного кода?

Хочу статистикой результаты подытожить.

Результаты чего? Тут речь об обучении. Скорость обучения будете измерять?

Результаты чего?

работы предложенных вариантов перебора

Скорость обучения будете измерять?

нет, затраченное время
Очень много лишних вопросов.

Действительно. Некогда думать, надо оптимизировать!

Почему не так?
shortnames = []
for person in celebrities:
	shortname = person.split()[0][0] + '.' + person.split()[1][0]
	shortnames.append(shortname)


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

Этот индекс нужен был для иллюстрации одного из этапов. Цель статьи — показать именно все этапы. Понятно, что всю задачу можно вообще в одну строку генераторным выражением решить.

Но ведь…
shortnames=([f"""{person.split()[0][0]}.{person.split()[1][0]}.""" for person in celebrities])

но я…
shortnames = list(map(lambda person: f"""{person.split()[0][0]}.{person.split()[1][0]}.""", celebrities))

ой все…
shortnames = list(map(lambda person: "".join(map(lambda p: f"""{p[0]}.""", person.split())), celebrities))
А потом приходит Sting (имеет право знаменитость иметь только имя?), и ой, всё…
UFO landed and left these words here
А потом приходят Karl der Große, Pépin le Bref и ой все… все в печакле

Я к чему, к тому что можно придумать стотыщьмилиорнов проблем. Да их надо учитывать, но мы говорим об учебе.

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

Без негатива, но удобно ли вам использовать строки которые больше 80 символов?
UFO landed and left these words here
UFO landed and left these words here

Хоть и с болью в душе, но соглашусь). На самом деле мне обычно 80 строк хватает даже на длинные переменные и все такое, однако бывают места, как например с теми же генераторами и так далее, где в 80 ну уж никак не умещается и приходится изводится. Но вот не могу перейти на 100 или даже более. Уже и привычка и кажется слегка неудобным.

Так используй перенос на другую строку ) почти все хорошо форматируется, и генераторы и длинные сигнатуры, проблема есть только с условиями, chaining методами и контекстными выражениями. Последние поправили в python3.10, а первые два можно форматировать через tuple который распаковывается автоматически.
instance\
    .some_method()\
    .some_method()\
    .some_method()

(instance
 .some_method()
 .some_method()
 .some_method())

if a is None and\
    b is None and\
    c is None:
    pass

if (a is None and
    b is None and
    c is None):
    pass
Был бы я программистом, я бы что то ответил.
А так, прошу прощения, я в этой теме не компетентен.

Спасибо всем тем парням, что пишут в одну строку. Люблю вас.

Многие из нас сначала писали многострочник, но потом стало скучно и начали сворачивать в одну строку (это я про списковые включения, если что...).
Автор в начале сам привел сравнение с обучением езды на автомобиле.
Так вот, продолжая это сравнение, приведенное здесь объяснение цикла я бы сравнил с обучением руления автомобиля через объяснение каким ими образом червячная передача передает управление от руля колесам. Оно надо это понимать осваивая азы руления?

Может действительно вспомить как мы учились рулить на велосипеде, а потом на автомобиле – повернул руль и поехал в нужную сторону.

Программирование занятие практическое. Может проще объяснить на практике пройдя по цепочке:

for item in celebrities:
print(item)

for item in celebrities:
print(item, item[0])

for item in celebrities:
print(item, item[0], item.find(' '))

for item in celebrities:
print(item, item[0], item[item.find(' ') + 1])

for item in celebrities:
print(item[0],'.',item[item.find(' ') + 1],'.')

OutList = [item[0]+'.'+item[item.find(' ') + 1]+'.' for item in celebrities]
Именно.
Статья автора — пример того, как нельзя обучать. Абсолютно непонятно для новичков, какие-то странные отсылки, сложные фразы и слова. Вместо того, чтобы наглядно и понятно показать, чтобы даже бабушки и дети поняли — какие-то странные вставки в этапе 3 и 5 со строкой resident, которые вообще ни к чему, от которых у обучаемых голова пухнет от вопроса «зачем они здесь?? Что за херь? Зачем тут upper, если его нет в финальном коде?». Какие то «группы объектов», «цель написать цикл». Ага, смешно, ещё даже никто не знает, что такое цикл, и главное зачем нужен, а куча абзацев какой-то галиматьи. Очень сложно читать, уловить мысль, даже после нескольких прочтений.
«Придётся перебрать все индексы списка. Какой командой это сделать — думаю, подсказки не нужно.» — супер, мы же первый раз учим циклам, конечно подсказки не нужны. Зато мы выльем какой-то лишней воды и левых примеров, которые вообще сбивают с толку, на лишних 5 абзацев, которые вообще ни к чему.

Автор, если ты обучаешь новичков, формулируй так, чтобы понимали даже дети.
p.s. то что нельзя два раза делать один и то же person.split() — это надо говорить сразу. А то потом такие же люди идут в js и у нас фронтенд тормозит от таких деятелей, которые не догадываются о кэшировании в переменной.

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

А. Так вот в чём дело...

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

Дочитал абзац до конца, чтобы выяснить, что в данном примере есть конвейерная лента и куда же с такой аналогией движется память. Неудачно.

Хорошая статья, хорошая подача (ну, есть некоторые опечатки и непонятности для новичков, правда. Речь идет в частности о разъяснении примера с резидентом, немного витиевато как по мне).
Я бы попросил автора написать на тему выборки (алгоритм выборки) из словарей в словарях, списки в словарях, словари в списках. Вот здесь очень нужны алгоритмы, так как для новичков это достаточно сложная тема, по-крайней мере для тех, кто впервые приступает к знакомству с каким бы то ни было языком программирования.
Наверняка, автор обучает и по запрашиваемой теме.
Спасибо.
Sign up to leave a comment.

Articles