Дубликаты не найдены

+2

Это что, коуб без звука?
А в этом ещё какой смысл?

+1

Coub вживую))

Похожие посты
7248

Шутки над программистами

Как-то раз наша большая ИТ-компания решила устроить новогодний корпоратив.

Это потом у нас появился постоянный ведущий, очень адекватный, а тогда взяли какого-то со стороны.

Он проникся, что мы ИТ, и весь вечер мочил шутки про программистов, свежие и не очень.

И весь вечер мы, несколько десятков инженеров-внедренцов, искоса поглядывали на столик, где угрюмо сидели все четверо наших программистов.

96

Встроенные типы данных (их назначение, методы и стандартное поведение) - Строки (часть 1)

Один из самых недооценённых начинающими питонистами встроенных типов данных - строки. Как недавно признался один из студентов: "Когда я встречаю строки - сразу иду гуглить". И это странно, ведь работа с текстом неизбежна.


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


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


Все нижеприведённые примеры являются строками в понимании питона:

s = 'text' # одинарные апострофы
s = "text" # одинарные двойные кавычки
s = '''text''' # тройные апострофы
s = """text""" # тройные двойные кавычки

Строкой является любой символ (или последовательность символов), заключённый в литералы строк, в т.ч. пробелы, цифры, знаки препинания.

# Это всё строки
s = '' # пустая строка (без символов между литералами) - тоже строка
s = " " # это строка из одного пробела
s = 'мама мыла раму'
s = "1234" # это не число, это строка
s = " Привет, мир! "

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


В чём разница одинарных и тройных литералов? Стандартно для объявления строк в коде мы используем одинарные кавычки или апострофы. И чаще всего такие строки являются короткими.


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

Что значит короткая и длинная строка? Для ответа на этот вопрос вспомним PEP8: длина строки кода не должна превышать 80 символов. Пока строка текста не превышает этот предел - она считается короткой. Как только текст требует переноса - строка становится длинной.


Экранирование

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

>>> s = "text" # одинарные двойные кавычки
>>> s
'text' # в выводе - одинарные апострофы

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


Сейчас внимательно следите за порядком слов "кавычки" и "апострофы". Если внутри самой строки должны содержаться апострофы или кавычки, то сама строка должна обрамляться соответственно кавычками или апострофами:

>>> "A.Dumas - D'Artagnan et les trois mousquetaires"
"A.Dumas - D'Artagnan et les trois mousquetaires"
>>> 'Ледокол "Ленин"'
'Ледокол "Ленин"'

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

1. использовать тройные кавычки или апострофы (при чём без разницы, что вы из них выберете),

>>> """O'Reilly published D.Beazley's book "Python Cookbook" in 2013"""
'O\'Reilly published D.Beazley\'s book "Python Cookbook" in 2013'

2. использовать экранирование специальным символом обратного слэша - \.

>>> 'O\'Reilly published D.Beazley\'s "Python Cookbook" in 2013'
'O\'Reilly published D.Beazley\'s "Python Cookbook" in 2013'
>>> "O'Reilly published D.Beazley's \"Python Cookbook\" in 2013"
'O\'Reilly published D.Beazley\'s "Python Cookbook" in 2013'

Как вы видите, в экранировании нуждаются символы, совпадающие с литералами - главное не запутаться, особенно, если текста много.


В экранировании также нуждаются специальные символы, при использовании которых в поведении строк происходят те или иные изменения. За полным списком таких символов и за примерами использования я вас пошлю вот сюда. Здесь же я опишу только те, которые чаще всего используются на деле (некоторые примеры я позаимствовал оттуда же).


Однако, прежде чем продолжить, хочу сделать ремарку для тех, кто родился в эпоху мобильных телефонов: некоторая терминология в статье, куда я вас отправил, относится к эре печатных машинок. Если вы не знаете, что такое звонок, каретка и как её переводить - "Ok, Google! Устройство печатной машинки".


Итак,

\ - если после символа \ сразу нажать Enter, то это переведёт каретку на новую строку:

>>> s = 'Это будет очень\
... , очень-очень\
... , ну прям оооооочень\
... длинная строка'
>>>
>>> s
'Это будет очень, очень-очень, ну прям оооооочень длинная строка'

\\ - экранирование символа обратного слеша (полезно при работе с файловой системой винды):

>>> s = 'D:\\мои документы\\книги\\Лутц.pdf'
>>> s
'D:\\мои документы\\книги\\Лутц.pdf'

\n - перевод каретки (новая строка):

>>> s = "Мама мыла раму\nМила раму мыла"
>>> print(s) # только функция print понимает, что делать со спецсимволами
Мама мыла раму
Мила раму мыла
>>> s # в этом случае просто выводится содержимое переменной
'Мама мыла раму\nМила раму мыла'

\t - горизонтальный отступ слева от начала строки (горизонтальная табуляция (да, есть и вертикальная)):

>>> s = '0\t1\t\t2\t\t\t3'
>>> print(s)
0 1 2 3
>>> '0 1 2 3'
'0\t1\t\t2\t\t\t3'

Achtung! Achtung! Приятные новости: в длинных строках всё это не нужно! =)

>>> s = """Эта очень длинная строка
... сама переносится, сама табулируется
... сама экранируется \."""
>>> print(s)
Эта очень длинная строка
сама переносится, сама табулируется
сама экранируется \.
>>> s
'Эта очень длинная строка\nсама переносится, сама\tтабулируется\nсама экранируется \\.'
>>> s = """Но если вдруг вам будет очень нужно прописать здесь что-то вроде '\n', то вам нужно воспользоваться экранированием, чтобы \\n не выполнялся"""
>>> print(s)
Но если вдруг вам будет очень нужно прописать здесь что-то вроде '
', то вам нужно воспользоваться экранированием, чтобы \n не выполнялся

Функция print

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

>>> help(print)

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

Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.

Лаконично, просто и понятно. Вот её сигнатура:

def print(self, *args, sep=' ', end='\n', file=None):

Она говорит нам о том, что:

*args - функция всеядная, т.е. ожидает любых аргументов в любом количестве,

sep=' ' - при выводе нескольких аргументов для их отделения друг от друга по умолчанию используется пробел,

end='\n' - любой вывод по умолчанию заканчивается переводом каретки на новую строку,

file=None - по умолчанию вывод производится на экран (если в этот параметр передать имя конкретного файла, то информация запишется (будет выведена) в такой файл).


Собственно, что это вдруг я её вспомнил? Посмотрите ещё раз внимательно. В числе её параметров присутствуют такие вещи как sep=' ' и end='\n'. Оба этих параметра принимают любые строковые символы, в том числе экранируемые. Зачем это нужно знать? Затем, чтобы иметь возможность оформлять вывод по своему желанию.

>>> a = "Мама"
>>> b = "мыла"
>>> c = "раму"
>>> print(a, b, c) # стандартный принт трёх переменных
Мама мыла раму
>>> print(a, b, c, sep='\t') # делаем разделителем табуляцию
Мама мыла раму
>>> print(a, b, c, sep='\t', end='\n\n') # добавляем лишнюю пустую строку по окончанию вывода
Мама мыла раму
>>> print(a, b, c, sep='42')
Мама42мыла42раму
>>> print(a, b, c, sep='42', end='THE END')
Мама42мыла42рамуTHE END

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

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


Префиксы

Кроме самих кавычек и апострофов в питоне существуют так называемые префиксы, которые определяют подвид строки. Их немного, я перечислю все, но остановлюсь только на тех, с которыми вы столкнётесь раньше всего и будете в последствии сталкиваться регулярно. Такими префиксами являются (в скобках указаны альтернативные виды написания:

u (U) - строка символов юникода (если вы не используете Python2, то можете смело о нём забыть),
r (R) - сырая строка;
b (B) - строка байтов;
f (F) - форматированная строка,
fr (rf, fR, rF, Rf, Fr, FR, RF) - сырая форматированная строка
br (rb, rB, bR, Br, Rb, BR, RB) - сырая байтовая строка.

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


Префиксы указываются до литералов без пробелов, например:

>>> s = r'\a\n'
>>> s
'\\a\\n'

Сырые строки

Сырые строки - это строки, в которых действие экранируемых символов подавляется. Проще говоря - в этих строках всё выходит на принт в первозданном виде.

Повторю пример:

>>> s = '\a\nМама' # обычная строка
>>> print(s)
# в этом месте сработал символ переноса строки "\n"
Мама
>>> s = r'\a\nМама' # сырая строка
>>> print(s)
\\a\\nМама

Сырые строки можно использовать как минимум в трёх случаях:

- в регулярных выражениях,

- для хранения файловых путей Windows, поскольку в них содержатся обратные слэши;

- для хранения сложных математических формул в разметке LATEX.


Байтовые строки

Байтовыми строками являются строки, отражающие двоичную структуру любых данных, в том числе текста, картинок, музыки, видео и т.д. При работе с текстом такие строки возникают при кодировании строки методом encode():

>>> s = 'Mama'.encode()
>>> print(s)
b'Mama'
>>> s = "Мама"
>>> s = s.encode()
>>> print(s)
b'\xd0\x9c\xd0\xb0\xd0\xbc\xd0\xb0'

Если к вам вдруг прилетела байтовая строка, то чаще всего её можно привести в человеческий вид при помощи обратного метода decode():

>>> s = b'\xd0\x9c\xd0\xb0\xd0\xbc\xd0\xb0'
>>> s = s.decode()
>>> print(s)
Мама

Форматированные строки

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

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

Логично предположить, что для таких целей есть некий шаблон, который выводит на печать заранее посчитанную общую стоимость покупок. В шаблоне есть заготовленная стандартная фраза "Общая стоимость покупок - ". А что дальше? Кассир же не будет каждый раз писать туда новую сумму для каждого нового покупателя. Значения должны автоматически в неё подставляться - для этого и существуют форматированные строки.

В версии Python 3.6. наконец появилась замечательная альтернатива старому методу форматирования строк str.format() - префикс f (или в обиходе - f-строки), который делает эту процедуру приятной и лёгкой до невозможности. Но вы должны это увидеть и оценить.

Итак, до версии 3.6 нужно было делать примерно так:

# представим, что общая сумма как-то посчиталась раньше и содержится в переменной total_sum
>>> total_sum = 1000
>>> final_sum_template = 'Общая стоимость покупок - {} руб.'
>>> s = final_sum_template.format(total_sum)
>>> print(s)
Общая стоимость покупок - 1000 руб.

То есть, под значение из total_sum в шаблоне заготовлено отдельное место в виде {}. Для вставки в это место требуемого значения нужно вызвать метод .format(), куда передать переменную или непосредственно само значение - и только тогда строка будет полностью сформирована. В данном примере это выглядит не так жутко. Но представьте ситуацию, когда у вас есть куча значений, которые должны лечь в одну строку. Чтобы не потеряться, в шаблоне нужно было делать именованные аргументы, чтобы потом их можно было вызывать в .format() и передавать туда значения. Например:

>>> name = "Вася"
>>> surname = "Пупкин"
>>> age = 18
>>> template = 'Это {a}. Его фамилия {b}. Вчера ему исполнилось {c} лет.'
>>> s = template.format(a=name, b=surname, c=age)
>>> print(s)
Это Вася. Его фамилия Пупкин. Вчера ему исполнилось 18 лет.

И всё это длинно, долго, муторно... А вот всё то же самое, только в f-строке:

>>> name = "Вася"
>>> surname = "Пупкин"
>>> age = 18
>>> s = f'Это {name}. Его фамилия {surname}. Вчера ему исполнилось {age} лет.'
>>> print(s)
Это Вася. Его фамилия Пупкин. Вчера ему исполнилось 18 лет.

Как минимум, у нас минус одна строка кода - это уже классно. Нет, конечно же, можно метод .format() сразу вызывать у template, но тогда мы рискуем получить очень длинную строку кода. Вдруг предложение в шаблоне уже занимает 80 символов (кстати, в "старом" шаблоне их уже 70)? Но дело даже не в этом. Я надеюсь, вы смогли оценить то, насколько процесс формирования текста упростился в этом месте. По сути это уже готовое предложение без лишней головной боли. Здесь уже нет никаких именованных заготовок, ожидающих передачу аргументов. Здесь заготовки, в которых уже стоят нужные аргументы. Кроме того, f-строки работают заметно быстрее старого метода.


Если вам мало и я вас не убедил, то почитайте вот эту статью. Если же я вас убедил, то у вас мог возникнуть вопрос: "зачем тогда вот это вот всё про устаревший метод?" Дело в том, что его пока ещё не вывели из использования. Кроме того, некоторые библиотеки, особенно те, которые написаны задолго до версии Python 3.6. и до сих пор находятся в строю, упорно не переписываются под использование f-строк. При работе с ними возникает прямая необходимость прибегать к старому методу. Поэтому для интересующихся - ссылка на старый добрый str.format()


To be continued...


-----

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


Да, и тег моё - потому что всё написано моими руками, а не тупо понакопировано с других сайтов.


P.S. Большое спасибо всем моим подписчикам за поддержку и активность! Без вас я, возможно, не решился бы продолжать.


Ссылки на предыдущие посты:

1. Предлагаю помощь в освоении Питона

2. ПЕРВОЕ ЗНАКОМСТВО С PYTHON

3. Встроенные типы данных (их назначение, методы и стандартное поведение) - Введение

4. Встроенные типы данных (их назначение, методы и стандартное поведение) - Числа

Показать полностью
72

Ответ Seegurd в «Про perl и годовой баланс» 

Пара историй из моей практики:

1. Обратилась как-то ко мне одна первокурсница удалённой формы обучения помочь с экзаменом по информатике. Ну как помочь - задачки простые на бейсике и, когда я начал ей объяснять как просто это делается, она лишь заморгала глазками. Я всё понял и вскоре сбросил ей все решения.

Первая сессия. Каждому студенту предоставлялся диск с программами для курсовых и экзаменов в форме тестов, результаты которых нужно было высылать в ВУЗ.

Программы явно написаны на дельфи, информация в запароленных парадоксовских БД.

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

Позже ВУЗовские умники перенесли всё это в онлайн, но базы остались старые ;)


2. Друг устроился экспедитором в одну контору, где была куча рутинной работы в Экселе. Быстро смекнув что куда, написал макрос ускоряющий работу в разы.

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

78

Как стать грамотным разработчиком встраиваемых систем?

Доброго времени суток, в начале этого года я написал пост как жить чуть больше чем на МРОТ и тут же настал коронавирус. Через некоторое время меня сократили, и чет стало вообще грустно. Не знал куда податься, хотел попробовать себя в web разработчиках, но обстоятельства сложились так, что я  стал делать несложные проекты на ардуино, а теперь и на esp32, благо я понимаю в схемотехнике и моделировании, но был полным нулем в программировании (да и сейчас не далеко ушел). Но мне понравилось это направление и в будущем хочу стать серьезным разработчиком, не только на атмегах, esp и stm, но вообще на любых микроконтроллерных системах. И вот тут я опять столкнулся с отсутствием информации, в универе нас этому не учили и я понимаю, что могу не осознавать, что какие то вещи надо учить уже сейчас, например FreeRTOS, работа с аппаратной частью микроконтроллеров, взаимодействие программно с ними, высшая математика вдруг нужна оказалась и углубиться в нее надо. Просто поверхностное знание C++ и Phyton  не позволит что то серьезное создавать. Сам С++ это тоже не просто синтаксис, я знаю что в нем есть очень мощные инструменты, которыми те же ардуинщики не пользуются. Время у меня есть, минимум год, есть база, есть желание и заказы в этом направлении, очень простые, но на хлеб хватит. Хочу делать серьезные и крутые штуки. Может подскажите подходящие книги, может зарубежные каналы или даже курсы, если надо летом в Москву поеду. А вот поступать 3й раз в вуз точно не хочу, это бесполезно.

Просто прошу совета. Без рейтинга.

Жаль что только в 33 пришло осознание чем хочу заниматься.

P.S. Кстати в университете успел пообщаться с системами National Instruments, но было это лет 10 назад.

Как стать грамотным разработчиком встраиваемых систем? Без рейтинга, IT, Программирование, Встраиваемые системы, Arduino
9360

Ответ на пост «Про perl и годовой баланс» 

Ответ на пост «Про perl и годовой баланс» IT, Бухгалтерия, Отношения, Vba, Макрос, Программирование, Ответ на пост

Как сисадмин задумал на бухгалтерше жениться.


Я со своей будущей супругой тогда работал в одной конторе и в одном кабинете. Она бухгалтер, я - сисадмин. Мы только начали как-то общаться и слегка проявлять симпатию. Однажды пили чай вместе, болтали, и она рассказала, что уже неделю делает какую-то нудятину а-ля сведение нескольких огромных таблиц в Excel.


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


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


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

Ну и короче моих знаний VBA и макросов Excel хватило на то, чтобы через пару дней я презентовал ей первый вариант "программы", где достаточно было положить все файлы в одну папку, обозвать нужными именами и нажать кнопочку "Сделать красиво" на форме - и спустя пару минут был готов итоговый файл, удовлетворяющий искомому результату. Список появился, нужные строчки в исходных файлах выделялись цветом, чтобы их можно было легко найти.


Девушка была в восторге, еще бы, потратить две минуты времени на то, что она раньше делала неделю!

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

Мораль: знание даже основ программирования может пригодиться вам в совершенно непредсказуемых обстоятельствах. Или нет.

Показать полностью
12215

Про perl и годовой баланс

Работал я в банке, в ~2007 году. По приходу в этот банк - закупил новый сервер, поставил в туда новый опердень, поднял DC, протянул и настроил сеть, закупил и настроил новые машины для операционистов, всё завёл, всё работает. Ну, такой банк, да. Да, не было сети у многих. Но речь не об том.

Дело идёт к концу года. Я уже сижу и просто мониторю машины, бэкапы. Чегототам программирую от нечего делать.

Замечаю что главбух (Г) уже неделю задерживается чуть ли не до ночи. Интересуюсь что случилось.

Г:- Да вот, годовой баланс свожу

Я:- Ну так опердень же умеет. Давайте найду как

Г:- Да опердень то умеет но проблема в другом. Во первых, в опердне только часть транзакций, с того времени как внедрили. Во вторых, есть старый опердень и там ещё часть транзакций за исключением тех, которые туда не попали из-за аварий и от тех транзакций осталось только платёжки.

Я:- Так, и что вы делаете?

Г:- Ну вот у меня есть старый опердень, есть новый, есть текстовые файлики с платёжками. Вот это всё в эксель переношу и считаю.

Я:- Понял. Могу помочь. Рассказывайте что в итоге должно быть и как считать.

Главбух бровь подняла, но начала рассказывать. В итоге я понял что в принципе достаточно ей html странички, где по каждому счёту нужно показать остатки. Показала где какие данные.

Взял я в руки perl и пошёл говнокодить. Сначала разобрался с новым оперднем. Делал в него запрос, в БД, вытаскивал данные в нужном формате. Во вторых, старый опердень. БД - dbf. Тоже относительно просто откопал оттуда нужное. В третьих - файлики текстовые. Где-то cp866, гдето 1251... Конечно же регекспы! Провозился чуть дольше но и это осилил. Время от времени ходил к главбуху, показывал промежуточное и выяснял правильно ли иду. На третий день уже она начала мне помогать. Про двойную книгу рассказала, местами помогла найти ошибки в логике расчётов. В общем, недели две или три вот так вот мы с ней в команде работали и таки родили результат. Довольная была как не знаю даже кто. Говорила что сама бы провозилась месяца два минимум.

Собственноручно выписала мне премию хорошую такую за труды. И до сих пор при встрече всегда здоровается, улыбается интересуется делами и так далее.

153

ПЕРВОЕ ЗНАКОМСТВО С PYTHON

Общие понятия

Python (в русском языке распространено название пито́н или па́йтон) — кроссплатформенный высокоуровневый язык программирования общего назначения, ориентированный на повышение производительности разработчика и читаемости кода.


Эту фразу видели все, кто хоть раз в жизни открывал статью про Python на Википедии. Вроде бы всё просто и ясно, но как-то не очень. Уже здесь встречаются непонятные термины: кроссплатформенный, высокоуровневый… Дать ёмкое и понятное определение чему бы то ни было – это великое искусство. Поэтому, я думаю, стоит пояснить всё вышесказанное простыми словами. А простыми словами это выглядит примерно так: Пайтон – это язык программирования, который можно использовать на любой известной стандартной операционной системе (Windows, MacOs, Linux) и при помощи которого можно написать практически любую программу (от «Привет, мир!» до новой операционной системы или нового языка программирования). Звучит заманчиво, не так ли?


Пайтон был придуман в 1991 году голландцем Гвидо ван Россумом, также известным как «великодушный пожизненный диктатор». Именно он по сей день принимает окончательные решения о том, как именно будет развиваться язык. Кстати, последняя версия питона (3.9.0) вышла буквально на днях – 05.10.2020. Её главная особенность для новичков, на мой взгляд, в том, что для её установки требуется минимум Windows 10 (на семёрку она не инсталлируется). Всё, чему будут посвящены мои статьи, гарантированно будет актуальным для версий 3.6.0-3.9.0. Версии питона 2.Х здесь рассматриваться не будут, т.к. для разработки новых приложений они уже не используется, а те, кто всё ещё стоически поддерживает приложения, написанные на них, вряд ли будут всё это читать.



Объектно-ссылочная модель

В своих интервью Гвидо подчёркивал, что никогда не видел Python в качестве языка сугубо функционального программирования. С самого начала питон позиционировался как язык объектно-ориентированного программирования (ООП), однако, он на нём можно писать в абсолютно любой парадигме - структурное, обобщенное, объектно-ориентированное, функциональное и аспектно-ориентированное программирование. Не буду заострять внимание на том, что означает каждый из них. Если интересно - это легко гуглится. Что же касается ООП, то пайтон спроектирован таким образом, что абсолютно всё, что в нём есть, т.е. все типы данных, функции, методы, классы, переменные – всё это является объектами, то есть некоторыми сущностями, обладающими определённым состоянием и поведением, имеющими определённые свойства (атрибуты) и операции или действия над ними (методы). Что это означает на практике, мы увидим уже достаточно скоро, а пока что просто примите это и уверуйте, что это именно так.


Переменных (в привычном понимании – «контейнеров») в питоне не существует. Когда в коде встречается нечто вроде «а = 5», серьёзные бородатые программисты в свитерах вам скажут, что «а» - это переменная, в которую записано значение «целое число пять». В случае с питоном это утверждение правда и неправда одновременно. В питоне «целое число пять» – это самостоятельный неизменяемый объект, который лежит где-то в оперативной памяти вашего компьютера. Например, выполним в консоли интерпретатора следующую команду

>>> id(5)
1609562080

Этой командой мы узнаём адрес той ячейки памяти, где у нас лежит число 5 – это ячейка 1609562080 (у вас может быть другое значение – это неважно).

Следом выполним ещё пару команд:

>>> a = 5
>>> id(a)
1609562080

Оказывается, у переменной «а» тот же адрес, что и у самой пятёрки. Но ведь если в питоне всё является объектом, то переменная – это контейнер, а значит тоже объект, то у неё должен быть свой адрес? Ответ – нет. В питоне нет переменных-контейнеров. Вместо этого в питоне есть ссылки на объекты. В данном случае «а» - это ссылка на число 5. Как это ещё проверить? Очень просто. Выполним ещё одну команду

>>> b = 5
>>> id(b)
1609562080

То же самое?! Да, именно так. Переменная «b» ссылается всё на ту же самую пятёрку. Последняя проверка этой теории:

>>> a is b
True

Переменная «а» - это то же самое, что и переменная «b», и любая другая «переменная», которая будет ссылаться на пятёрку, какое бы имя вы ей не придумали.


Возникает вопрос: а что же тогда такое знак «=» в данном случае? В питоне знак «=» не знак равенства, а оператор присваивания. Равенство в питоне выражается через оператор «==», который используется исключительно в булевой логике, т.е. для сравнения значений и/или содержимого разных объектов.


Итак, вывод: в питоне переменных нет, знак «=» не приравнивает значение к переменной и не записывает значение в переменную, а присваивает какому-либо объекту именную ссылку для удобства обращения.



Динамическая типизация

Динамическая или как принято в питонической среде - «утиная типизация». Это очень простая концепция: «Если что-то выглядит как утка, плавает как утка и крякает как утка, то это наверняка и есть утка».


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


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

>>> a = 5
>>> type(a)
<class 'int'>
>>> a = str(a)
>>> type(a)
<class 'str'>
>>> a
'5'

Вот и всё, теперь переменная «а» ссылается уже не на целочисленный объект 5, а на строковый объект 5. Для наглядности я сразу запросил тип каждого из объектов, и оснований не верить результатам лично у меня нет: вначале пятёрка – это число, в конце – строка. Об этом говорит не только type(a), но и само значение, которое раньше было голой пятёркой, а теперь обрамлено кавычками.


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



Стиль кодирования. PEP8

У каждого языка программирования, как и любого другого языка, есть свои законы, которым он подчинён. Если русском языке мы пишем названия месяцев со строчной буквы (9 мая, 8 марта), то в английском, например, месяцы всегда пишутся с прописной (January, 4th of July). Питон также имеет свою семантику, грамматику и свой синтаксис. Основным сводом законов, определяющих требования к красивому и качественному стилю кодирования определены в документе, который называется Python Enhancement Protocol 8 или PEP8. Основные правила на самом деле достаточно просты, но почему-то на каждом новом курсе я встречаю людей, упорно их игнорирующих.


Давайте начнём с того, что Python – язык международный. Это вам не 1С, на котором пишут в буквальном смысле по-русски. В питоне всё по-английски. Всё и всегда. Мне попадались 2 уникума, которые упорно именовали переменные по-русски. Объясняли они это тем, что «так понятнее». Нет, если вы не знаете английского, то вам, возможно, будет понятнее. Но нужно учитывать, что IT – это англоязычная среда, все программы, и 90% документации написаны именно на английском, и, в конце концов, ваш код могут читать (а большинство времени будет потрачено именно на его чтение, причём не только вами) люди, не знающие русского. Ну или давайте наоборот: вам прислали на проверку кусок кода, где половина на хинди или суахили. Как вам такое? Возьмите себя в руки и если вы не знаете или плохо знаете английский – начните его учить с нуля. Не брезгуйте онлайн-переводчиками и словарями для выбора имён переменных и функций – это не стыдно.


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

>>> a = 5
>>> b = "mama"
>>> for i in b:
... print(i * a)
...
mmmmm
aaaaa
mmmmm
aaaaa

Казалось бы, всё работает – что ещё нужно? Да, работает. Даже если бы переменные были названы по-русски или по-китайски, то же бы работало, так как питону глубоко всё равно, какой алфавит вы используете для обозначения ссылок - он всё это перерабатывает в байтовые представления символов юникода. Кошмар же заключается в том, что не соблюдено главное правило питониста: код должен быть читаемым. Читаемым человеком, его глазами. Возможно, сейчас это будет сложно, но попробуйте представить, что между объявлением переменных и циклом for не ноль строк, как сейчас, а 100-150-200. Да, это утрированный пример, но всё-таки. Никто через 100, да даже через 50 строк не вспомнит, что такое переменные «a» и «b». Ну какие-то там переменные, но что в них лежит, на что они ссылаются? Может это число и строка? А может это строка и число? А может это и не строка и не число? Надо лезть выше, искать их, разбираться. Опять всё сводится к бесполезной трате времени.


Не проще ли было сразу назвать эти переменные по-человечески (в прямом смысле)? Давайте попробуем:

>>> number = 5
>>> string = "mama"
>>> for i in string:
... print(i * number)
...
mmmmm
aaaaa
mmmmm
aaaaa

Выхлоп не изменился, но мозгу становится понятнее, глазу приятнее. Осталось разобраться с «i».

В строке «for i in string» «i» является ничем иным как временной переменной. Её тоже нужно уметь красиво и понятно назвать. Как показывает моя собственная практика, иногда хорошее, грамотное название переменной снимает у студентов возникшие вопросы по дальнейшим действиям. Они внезапно начинают понимать, что делали не так и что нужно на самом деле делать и куда двигаться. Так давайте уже её переделаем и пойдём дальше:

>>> number = 5
>>> string = "mama"
>>> for letter in string:
... print(letter * number)
...
mmmmm
aaaaa
mmmmm
aaaaa

Именно это и описано в PEP8 – как писать качественный код, отвечающий требованиям и стилю Python, или как принято говорить – pythonic style или pythonic way. Многие из нас, кто ещё в школе пытался учиться программированию, помнят такой язык, как Basic или QBasic. Потом он перерос в VBA и до сих пор (к сожалению…) используется для написания макросов в офисных программах Microsoft. И в связи с этим у многих из нас при изучении питона всплывает Basic style – стиль кодирования на Basic. Pythonic style ушёл намного дальше. Читаемость кода за счёт простоты синтаксиса повысилась в разы. Вот для наглядности пример.

Задача: получите из входного потока число и напечатайте сумму его цифр.

Как бы эту задачу решило большинство в «Basic style»:

>>> number = input()
>>> summa = 0
>>> for dig in number:
… if dig in '0123456789':
…  summa = summa + int(dig)
>>> print(summa)

Как это решается в «Pythonic style»:

>>> print(sum(int(x) for x in input() if x.isdigit()))

Возможно, вам сейчас ничего не понятно из того, что тут написано, но вам стоит оценить хотя бы то, сколько сил и времени сэкономлено за счёт сокращения количества строк. «Достаточно одной таблетки» (с). В данном случае – одной строки, а результат одинаковый.


Давайте тезисно определим основные правила синтаксиса:

- используя питон, мы пишем на английском языке;

- все названия переменных, функций, классов должны как можно полнее отражать их суть и содержание;

- названия переменных и функций принято писать в нижнем регистре, разделяя слова подчёркиванием (snake_case):

# ПРАВИЛЬНО
my_number = 42
def my_function():
#НЕ правильно
MyNumber = 42
Mynumber = 42
MYNUMBER = 42
mynumber = 42
МоЙнОмЕр = 42
def MyFunction():
def Myfunction():
def MYFUNCTION():
def myfunction():

- названия классов принято писать в CamelCase – слова пишутся с заглавной буквы без разделителей между словами:

# ПРАВИЛЬНО
class MySuperPuperClass:

#НЕ правильно
все остальные варианты

- для названия переменных, функций и классов нельзя использовать зарезервированные слова (слова, которые зашиты в питоне в качестве операторов, имен встроенных функций, классов и их атрибутов и методов);

- конец строки является концом инструкции (никакие специальные знаки не требуются);

- вложенные инструкции объединяются в блоки по величине отступов. 1 отступ = 4 пробела;

- вложенные инструкции в Python записываются в соответствии с одним и тем же шаблоном: основная инструкция завершается двоеточием, вслед за которым располагается вложенный блок кода с отступом в 4 пробела под строкой основной инструкции.

if a == 1:
print('mama' * 3)  # 4 пробела после двоеточия

- в случае, если длина инструкции превышает 80 знаков, допустимо записывать одну инструкцию в нескольких строках. Достаточно ее заключить в пару круглых, квадратных или фигурных скобок:

if (a == 1 and b == 2 and
c == 3 and d == 4):  # продолжение инструкции выравнивается по открывающей скобке
print('mama' * 3)  # 4 пробела после двоеточия

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

>>> if x > y: print(x)

- технически возможно записать несколько инструкций в одной строке, разделяя их точкой с запятой (но такой способ не приветствуется, т.к. не соответствует стилю кодирования PEP8):

>>> a = 1; b = 2; print(a, b)

Это основные вещи, которые нужно выучить. Благо, что мы живём в 21 веке и рабочие среды уже давно умеют анализировать наш код на соответствие стилю, а также полно разнообразных сторонних линтеров. Поэтому, если вы переживаете, что вы не осилите этот момент – ваша IDE вам подскажет, где что поправить, и в большинстве случаев – сама же и поправит. Если она этого самостоятельно делать не умеет, то можно воспользоваться сторонними линтерами.

Что будет, если на всё это забить и писать как бог на душу положит? Да ничего. Просто вас проклянут до десятого колена те, кто будет это читать, а в остальном ничего.



Дзен питона

Также у питона есть свой собственный сборник мантр, который также призван формировать хороший стиль у разработчиков. Выполним в консоли команду:

>>> import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Перевод на русский конечно же существует:


Дзен Пайтон (составлен Тимом Питерсом)
Красивое лучше, чем уродливое.
Явное лучше, чем неявное.
Простое лучше, чем сложное.
Сложное лучше, чем запутанное.
Плоское лучше, чем вложенное.
Разреженное лучше, чем плотное.
Читаемость имеет значение.
Особые случаи не настолько особые, чтобы нарушать правила.
При этом практичность важнее безупречности.
Ошибки никогда не должны замалчиваться.
Если не замалчиваются явно.
Встретив двусмысленность, отбрось искушение угадать.
Должен существовать один — и, желательно, только один — очевидный способ сделать это.
Хотя он поначалу может быть и не очевиден, если вы не голландец (это такая шутливая отсылка к Гвидо).
Сейчас лучше, чем никогда.
Хотя никогда зачастую лучше, чем прямо сейчас.
Если реализацию сложно объяснить — идея плоха.
Если реализацию легко объяснить — идея, возможно, хороша.
Пространства имён — отличная вещь! Давайте будем делать их больше!

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



«Hello, world!»

Пришло время написать первую программу. Хотя на самом деле это не так. Свою первую программу все те, кто скачал и поставил себе пайтон, уже написали. С точки зрения программирования рабочей программой называется та программа, которая запускается и не выдаёт ошибок. Так что с этой точки зрения пустой код – это вполне рабочая программа. Вы можете в этом сами убедиться, создав пустой файлик с расширением .py и запустив его через вашу IDE. Физически ваша «программа» ничего не выдаст, но интерпретатор вам скажет «Process finished with exit code 0», что означает, что код был запущен и завершен без ошибок, а значит он вполне рабочий.


Под первой программой стандартно понимается программа, выводящая на экран сообщение «Hello, world!» - то есть нам нужно просто вывести текст на экран. Для вывода на экран существует встроенная функция «print». Для вызова функции нам необходимо добавить к её названию круглые скобки: print().


Можно написать в консоли print(), нажать Enter – программа отработает без ошибок, но ничего напечатано не будет. И это нормально, ведь мы не сказали функции, что именно ей нужно напечатать. Пока что мы просто заставили её сработать вхолостую, что она и сделала.

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


Текст в питоне – это тип данных «строка» (подробнее о них мы поговорим в следующий раз, и поверьте, там есть о чём). Строки должны быть заключены в кавычки.


Hello, world! – это не строка.

"Hello, world!" – а вот это уже строка.


Значит именно так мы и должны передать её в функцию print.


Итак,

>>> print("Hello, world!")
Hello, world!

Отлично, мы сделали это! Но, можно ещё интереснее. Например, можно записать строку в переменную, передать в функцию эту переменную и распечатается та же строка:

>>> hello = "Hello, world!"
>>> print(hello)
Hello, world!

Мне надоело здороваться со всем миром, я хочу разнообразия. Для этого я хочу сам говорить программе, с кем поздороваться. Для этого я вызову функцию ввода с клавиатуры «input».

>>> hello = "Hello, "
>>> name = input() # с клавиатуры вводим любое слово, например, Петя
>>> print(hello, name, "!")
Hello,  Петя !
>>> print("Hello, " + name + "!")
Hello, Петя!

На сегодня это всё, спасибо за внимание!


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

Да, и тег моё - потому что всё написано моими руками, а не тупо понакопировано с других сайтов.


P.S. Большое спасибо всем моим подписчикам за поддержку и активность! Без вас я, возможно, не решился бы продолжать.


Ссылки на предыдущие посты:

1. Предлагаю помощь в освоении Питона

Показать полностью
189

Знакомьтесь, Алексей Пахунов из Житомира

Программное обеспечение, которое отвечает за полёт Crew Dragon, пишет он. Старший разработчик ПО в группе Flight Software, SpaceX Илона Маска

Знакомьтесь, Алексей Пахунов из Житомира Программирование, Программист, Люди, Космос, SpaceX
1176

Максимальное наказание

Максимальное наказание Профессиональный юмор, Суд, Программирование, Наказание, IT юмор

— Я приговариваю вас к максимальному наказанию!

— А можно на один денёк побольше?

— Ладно, вы проведете -32768 лет в тюрьме.

5201

Программист-философ

Программист-философ Программист, Философия, Клонирование, Профессиональный юмор, IT юмор

— Если клонировать человека, будут ли они с клоном одним и тем же человеком?

— Зависит от того, клонировать по ссылке или по значению.

247

Программисты и работа на удаленке до того, как это стало мейнстримом

Программисты и работа на удаленке до того, как это стало мейнстримом Картинка с текстом, IT юмор, Странный юмор, Компьютер, Монитор, Удаленная работа, Программист, Айтишники

* "усердно трудимся" с 3 мониторами

Похожие посты закончились. Возможно, вас заинтересуют другие посты по тегам: