При этом мало кто из будущих разработчиков отдаёт себе отчёт в том, насколько сложные вещи обсуждаются на видеоуроках, которые они смотрят, и Zoom-семинарах, в которых они принимают участие. Люди молча кивают (или ставят плюсик в чате), когда им озвучиваются определения из разряда “Docker - программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации, контейнеризатор приложений”. Здесь в пояснении нуждается буквально каждое слово, но мало кто из преподавателей будет заниматься подобной расшифровкой. А взрослым учащимся детально вникать в такие вещи зачастую просто некогда: надо делать домашнее задание, разрабатывать выпускные проекты, а еще ведь и работать, и с близкими общаться, и домашние дела делать, а иногда даже и отдыхать.
Как раз в помощь тем, кто постеснялся признаться себе и/или окружающим в том, что чего-то не понял в непрерывном потоке программистского жаргона, и создан этот блог. Здесь об экстремально сложных вещах мы постараемся рассказать экстремально простым языком. “Если вы что-то не можете объяснить 6-летнему ребёнку, вы сами этого не понимаете”, - одна из распиаренных фраз, которую приписывают то Эйнштейну, то Фейнману, то ещё кому-то. Возможно, у неё и вовсе одного автора нет, для нас это неважно. Мы просто возьмём её на вооружение как девиз. Постараемся настолько разложить сложные вещи, чтобы на выходе получился набор простых. Мы освоим их, а потом заново из них соберем сложную вещь, которая от этого сложной быть не перестанет, но при этом станет хотя бы приблизительно понятной для нас.
Сложно? Непонятно? Мне тоже. Давайте разбираться вместе!
P.S. Статьи в рамках этой рубрики будут неизбежно критиковаться опытными (и не очень) разработчиками, что и неудивительно: я тоже только учусь. Ориентируясь на конструктивную критику, мы будем улучшать качество материалов, делая их более точными, но не в ущерб понятности.
Пост на сайте
Поддержать проект
Как раз в помощь тем, кто постеснялся признаться себе и/или окружающим в том, что чего-то не понял в непрерывном потоке программистского жаргона, и создан этот блог. Здесь об экстремально сложных вещах мы постараемся рассказать экстремально простым языком. “Если вы что-то не можете объяснить 6-летнему ребёнку, вы сами этого не понимаете”, - одна из распиаренных фраз, которую приписывают то Эйнштейну, то Фейнману, то ещё кому-то. Возможно, у неё и вовсе одного автора нет, для нас это неважно. Мы просто возьмём её на вооружение как девиз. Постараемся настолько разложить сложные вещи, чтобы на выходе получился набор простых. Мы освоим их, а потом заново из них соберем сложную вещь, которая от этого сложной быть не перестанет, но при этом станет хотя бы приблизительно понятной для нас.
Сложно? Непонятно? Мне тоже. Давайте разбираться вместе!
P.S. Статьи в рамках этой рубрики будут неизбежно критиковаться опытными (и не очень) разработчиками, что и неудивительно: я тоже только учусь. Ориентируясь на конструктивную критику, мы будем улучшать качество материалов, делая их более точными, но не в ущерб понятности.
Пост на сайте
Поддержать проект
🔥8👏2
Напоминаю, на нашем канале проводится мероприятие по типу "Тайного Санты".
Нас уже 8 участников!
Пост тут: https://t.iss.one/press_any_button/263
Форма для участия тут: https://forms.gle/adM65uCYJEPgSggW7
Нас уже 8 участников!
Пост тут: https://t.iss.one/press_any_button/263
Форма для участия тут: https://forms.gle/adM65uCYJEPgSggW7
🔥2
Ветер переменных
Автор: Андрей Лебедев
Да, переменные - это основа основ. Если вы изучали Python хотя бы месяц, то не могли пройти мимо них. Хотя какой там месяц - о переменных обычно рассказывают на первом же занятии. А если Python - это не первый ваш язык, то вы тем более в курсе, что значит “переменная”. И всё-таки я рекомендую вам продолжить чтение в любом случае, потому что здесь не всё так просто. Но мы попробуем упростить.
Автор: Андрей Лебедев
Да, переменные - это основа основ. Если вы изучали Python хотя бы месяц, то не могли пройти мимо них. Хотя какой там месяц - о переменных обычно рассказывают на первом же занятии. А если Python - это не первый ваш язык, то вы тем более в курсе, что значит “переменная”. И всё-таки я рекомендую вам продолжить чтение в любом случае, потому что здесь не всё так просто. Но мы попробуем упростить.
👍1
Что такое переменная?
Переменная (что очевидно из названия) - это то, что можно легко изменить. Чаще всего в объяснениях мелькает сравнение переменных с коробочками. Любая коробочка - переменная, потому что можно легко изменить её содержимое. Сначала положить в неё ручку. И тогда она будет содержать ручку. Потом ручку вынуть и положить туда смартфон. Коробочка та же, а содержание изменилось. Вот и в переменную мы можем положить строку, можем список, а можем даже целую функцию. Что положили, то там и “лежит”. И если мы содержимое изменим, называться переменная будет прежним образом (коробочка та же). Чаще всего на этом объяснение и заканчивается. Всем всё понятно, расходимся. Попробуем немного усложнить.
Что значит “коробочка”, куда попадает содержимое в виде строк, списков и всего прочего, что мы туда кладём? В языке C (Си), например, коробочка (то есть переменная) - это ячейка памяти. То есть прям вот коробочка и есть. Когда мы объявляем переменную, в недрах компьютера (как на складе) резервируется ячейка памяти (коробка определенного размера), куда и попадает содержимое, которое мы в нее решили положить. Если мы содержимое коробочки решим поменять, то коробочка (ячейка памяти) в прямом смысле остаётся той же самой.
А как обстоит дело в Python?
Совсем не так. При объявлении переменной тоже резервируется ячейка памяти (коробочка), но когда мы решаем в ту же переменную записать что-то другое, мы кладем это в другую ячейку памяти (новую коробочку), хоть и называется она точно так же. Потому что то, что мы называем “переменной” в Python, - вовсе не коробочка, а бирка, которую мы на нее наклеиваем. И когда мы меняем содержимое переменной, мы не кладем в ту же коробочку (ячейку памяти) что-то новое, а переклеиваем ту же самую бирку на новую коробочку с новым содержимым.
Если говорить совсем уж строго, переменная в Python - вообще не переменная в том смысле, в котором это слово употребляется в контексте языка C. Она скорее ссылка на объект (object reference) или имя (name).
Тогда почему мы называем одним и тем же словом (“переменная”) вещи, которые в Python и других языках различаются? Для упрощения: потому что используем мы их в разных языках схожим образом. Объявил переменную, положил в неё что-нибудь - и вперед: крути циклы, отправляй в функции, меняй содержимое. Чаще всего задумываться о том, что она там означает на самом деле - коробочку или бирку на ней, не придется.
А зачем тогда вообще об этом знать?
Всё-таки этот момент нужно уяснить, чтобы разобраться с другими важными вещами, которые напрямую с ним связаны:
- разницу между оператором “==“ и ключевым словом ‘is’
- нюансы изменяемости и неизменяемости объектов
- сложности поведения некоторых переменных, которые передаются в функции в качестве параметров
- динамическую типизацию и т.д. и т.п.
Всё это мы обязательно обсудим, но как-нибудь в другой раз. А сейчас закрепим коробочно-бирочную аналогию на примере.
Пример
Разберёмся в том, что только что произошло на наших глазах.
1️⃣ Мы завели бирку (переменную) name и наклеили ее на коробку (ячейку памяти), в которую положили строку “Стэн”. Дальше мы захотели посмотреть на уникальный заводской номер этой коробки (вызвали функцию id, которая возвращает уникальный адрес ячейки памяти, в которой хранится объект).
Переменная (что очевидно из названия) - это то, что можно легко изменить. Чаще всего в объяснениях мелькает сравнение переменных с коробочками. Любая коробочка - переменная, потому что можно легко изменить её содержимое. Сначала положить в неё ручку. И тогда она будет содержать ручку. Потом ручку вынуть и положить туда смартфон. Коробочка та же, а содержание изменилось. Вот и в переменную мы можем положить строку, можем список, а можем даже целую функцию. Что положили, то там и “лежит”. И если мы содержимое изменим, называться переменная будет прежним образом (коробочка та же). Чаще всего на этом объяснение и заканчивается. Всем всё понятно, расходимся. Попробуем немного усложнить.
Что значит “коробочка”, куда попадает содержимое в виде строк, списков и всего прочего, что мы туда кладём? В языке C (Си), например, коробочка (то есть переменная) - это ячейка памяти. То есть прям вот коробочка и есть. Когда мы объявляем переменную, в недрах компьютера (как на складе) резервируется ячейка памяти (коробка определенного размера), куда и попадает содержимое, которое мы в нее решили положить. Если мы содержимое коробочки решим поменять, то коробочка (ячейка памяти) в прямом смысле остаётся той же самой.
А как обстоит дело в Python?
Совсем не так. При объявлении переменной тоже резервируется ячейка памяти (коробочка), но когда мы решаем в ту же переменную записать что-то другое, мы кладем это в другую ячейку памяти (новую коробочку), хоть и называется она точно так же. Потому что то, что мы называем “переменной” в Python, - вовсе не коробочка, а бирка, которую мы на нее наклеиваем. И когда мы меняем содержимое переменной, мы не кладем в ту же коробочку (ячейку памяти) что-то новое, а переклеиваем ту же самую бирку на новую коробочку с новым содержимым.
Если говорить совсем уж строго, переменная в Python - вообще не переменная в том смысле, в котором это слово употребляется в контексте языка C. Она скорее ссылка на объект (object reference) или имя (name).
Тогда почему мы называем одним и тем же словом (“переменная”) вещи, которые в Python и других языках различаются? Для упрощения: потому что используем мы их в разных языках схожим образом. Объявил переменную, положил в неё что-нибудь - и вперед: крути циклы, отправляй в функции, меняй содержимое. Чаще всего задумываться о том, что она там означает на самом деле - коробочку или бирку на ней, не придется.
А зачем тогда вообще об этом знать?
Всё-таки этот момент нужно уяснить, чтобы разобраться с другими важными вещами, которые напрямую с ним связаны:
- разницу между оператором “==“ и ключевым словом ‘is’
- нюансы изменяемости и неизменяемости объектов
- сложности поведения некоторых переменных, которые передаются в функции в качестве параметров
- динамическую типизацию и т.д. и т.п.
Всё это мы обязательно обсудим, но как-нибудь в другой раз. А сейчас закрепим коробочно-бирочную аналогию на примере.
Пример
name = "Стэн"
print(id(name))
# 4427735920
same_name = "Стэн"
print(id(same_name))
# 4427735920
name = "Эрик"
print(id(name))
# 4428719728
Разберёмся в том, что только что произошло на наших глазах.
1️⃣ Мы завели бирку (переменную) name и наклеили ее на коробку (ячейку памяти), в которую положили строку “Стэн”. Дальше мы захотели посмотреть на уникальный заводской номер этой коробки (вызвали функцию id, которая возвращает уникальный адрес ячейки памяти, в которой хранится объект).
👍1
2️⃣ Далее мы завели переменную same_name и записали в нее ту же самую строку “Стэн”. Проверяем адрес ячейки и… он оказывается тем же самым. Почему? Потому что на нашем складе (в памяти) уже хранится коробка (ячейка) с таким же точно содержимым. Мы завели её на предыдущем шаге. Зачем создавать ещё одну такую же коробку для такого же содержимого, если можно просто наклеить на уже существующую коробку ещё одну бирку (нашу новую переменную)? Незачем, она будет занимать лишнее место. Точно так же "думает" и интерпретатор Python. В целях экономии памяти он проверяет, не создавалась ли уже ранее строка, которую мы пытаемся создать. И если она-таки создавалась, новая переменная привязывается к уже существующей ячейке памяти. Всегда ли так происходит? Нет, не всегда, но об этом поговорим подробнее в следующих постах. А пока запомним, что за экономией пространства на нашем складе с коробками следят довольно внимательно.
3️⃣ Наконец, мы меняем содержимое нашей первой переменной name, записав туда новую строку “Эрик”. Проверяем уникальный адрес ячейки, и он теперь другой! Почему? Потому что мы просто переклеили бирку на новую коробку. В старой у нас по-прежнему лежит “Стэн”, и на неё наклеена бирка same_name…
Если это всё ещё выглядит сложно и непонятно, советую немножко поиграться с этим и самостоятельно всё “пощупать” в PyCharm или любой другой удобной IDE. Заранее предупреждаю: если вы будете экспериментировать с другими типами данных, результаты могут отличаться, но об этом подробнее поговорим в другой раз.
Пост на сайте
Поддержать проект
3️⃣ Наконец, мы меняем содержимое нашей первой переменной name, записав туда новую строку “Эрик”. Проверяем уникальный адрес ячейки, и он теперь другой! Почему? Потому что мы просто переклеили бирку на новую коробку. В старой у нас по-прежнему лежит “Стэн”, и на неё наклеена бирка same_name…
Если это всё ещё выглядит сложно и непонятно, советую немножко поиграться с этим и самостоятельно всё “пощупать” в PyCharm или любой другой удобной IDE. Заранее предупреждаю: если вы будете экспериментировать с другими типами данных, результаты могут отличаться, но об этом подробнее поговорим в другой раз.
Пост на сайте
Поддержать проект
🔥9
Django + AIOgram3 + Redis - Отправка поста с Django в AIOgram
Автор: Иван Ашихмин
С момента запуска проекта возникла необходимость делать двойную работу - размещать пост на сайте и дублировать его в Telegram-канале. Я старался найти решение так, чтобы на сайте можно было заполнить необходимые поля, отформатировать текст и разместить пост. После чего данный пост должен разместиться на канале автоматически.
Решение было найдено не сразу. Вариантов реализации отправки данных из
Автор: Иван Ашихмин
С момента запуска проекта возникла необходимость делать двойную работу - размещать пост на сайте и дублировать его в Telegram-канале. Я старался найти решение так, чтобы на сайте можно было заполнить необходимые поля, отформатировать текст и разместить пост. После чего данный пост должен разместиться на канале автоматически.
Решение было найдено не сразу. Вариантов реализации отправки данных из
Django в AIOgram3 достаточно много, я остановился на связке Django + AIOgram3 + Redis. И в этом посте расскажу, как можно реализовать такой функционал.Действия проводятся на основе файлов из постов "Django 35.2. Расширенный профиль пользователя" и "AIOgram3 15. Обработка события вступления или покидания чата".
Продолжение в посте на Boosty (платный контент)
Пост на сайте
Поддержать проект
Продолжение в посте на Boosty (платный контент)
Пост на сайте
Поддержать проект
Напоминаю, на нашем канале проводится мероприятие по типу "Тайного Санты".
Нас уже 8 участников!
Пост тут: https://t.iss.one/press_any_button/263
Форма для участия тут: https://forms.gle/adM65uCYJEPgSggW7
Нас уже 8 участников!
Пост тут: https://t.iss.one/press_any_button/263
Форма для участия тут: https://forms.gle/adM65uCYJEPgSggW7
🔥1
Оглавление для серии постов рубрики "Код в мешке".
Для удобства навигации по предстоящим материалам, в данном посте будут публиковаться ссылки на сообщения.
Новая рубрика "Код в мешке"
Ветер переменных
== != is (о разнице между оператором "==" и ключевым словом "is")
Питон на измене
Декораторы в питоне
Основы ООП на Python. ч. 1
ООП на Python. ч. 2. Статические методы
ООП на Python, ч. 3. Методы __str__ и __repr__
#код_в_мешке #оглавление
Для удобства навигации по предстоящим материалам, в данном посте будут публиковаться ссылки на сообщения.
Новая рубрика "Код в мешке"
Ветер переменных
== != is (о разнице между оператором "==" и ключевым словом "is")
Питон на измене
Декораторы в питоне
Основы ООП на Python. ч. 1
ООП на Python. ч. 2. Статические методы
ООП на Python, ч. 3. Методы __str__ и __repr__
#код_в_мешке #оглавление
🔥4
Приветствую!
В длинных постах можно запутаться поэтому, собираю воедино всё, что есть на данный момент.
Оглавления:
Для удобства навигации есть посты с оглавлениями по темам:
"Сайт на Django"
"Telegram-бот на AIOgram3"
"Применение Docker"
"Полезные инструменты"
"Код в мешке"
Ресурсы канала:
Уютный и немного безумный чат канала.
Бот с материалами к постам
Сайт со всеми постами
Поддержка.
Если вам нравится канал и выходящий материал, поделитесь ссылкой с людьми, кому это тоже может быть интересно.
Также поддержать канал можно на Boosty.
Или внеся сайт в исключения вашего блокировщика рекламы.
В длинных постах можно запутаться поэтому, собираю воедино всё, что есть на данный момент.
Оглавления:
Для удобства навигации есть посты с оглавлениями по темам:
"Сайт на Django"
"Telegram-бот на AIOgram3"
"Применение Docker"
"Полезные инструменты"
"Код в мешке"
Ресурсы канала:
Уютный и немного безумный чат канала.
Бот с материалами к постам
Сайт со всеми постами
Поддержка.
Если вам нравится канал и выходящий материал, поделитесь ссылкой с людьми, кому это тоже может быть интересно.
Также поддержать канал можно на Boosty.
Или внеся сайт в исключения вашего блокировщика рекламы.
🔥4
== != is
Автор: Андрей Лебедев
Поговорим о разнице между оператором "==" и ключевым словом "is". Если до этого вы не читали мой пост о переменных в питоне и коробочках, сейчас самое время сделать это, потому что мы будем продолжать всё ту же аналогию.
Итак, вспомним, что у нас есть:
*️⃣ Переменная - она же бирка на коробочке
*️⃣ Коробочка - она же ячейка памяти
*️⃣ Заводской номер коробочки - он же адрес ячейки памяти
*️⃣ Содержимое коробки - значение
*️⃣ Склад - память в целом.
Вспомнили? Отлично. Есть шанс, что если с разработкой не срастётся, всегда можно будет устроиться работать на склад. Шутка, всё обязательно получится, для этого мы здесь.
Автор: Андрей Лебедев
Поговорим о разнице между оператором "==" и ключевым словом "is". Если до этого вы не читали мой пост о переменных в питоне и коробочках, сейчас самое время сделать это, потому что мы будем продолжать всё ту же аналогию.
Итак, вспомним, что у нас есть:
*️⃣ Переменная - она же бирка на коробочке
*️⃣ Коробочка - она же ячейка памяти
*️⃣ Заводской номер коробочки - он же адрес ячейки памяти
*️⃣ Содержимое коробки - значение
*️⃣ Склад - память в целом.
Вспомнили? Отлично. Есть шанс, что если с разработкой не срастётся, всегда можно будет устроиться работать на склад. Шутка, всё обязательно получится, для этого мы здесь.
❤2🔥1
Оператор "=="
Итак, для чего нужен оператор "=="? Он позволяет проверить, совпадает ли содержимое двух коробок на складе (значения, хранящиеся в двух ячейках памяти). Он похож на работника склада, который умеет выполнять только эту задачу и никакую другую. Негусто, конечно, но зато справляется он со своей функцией на ура.
Как поставить работнику задачу? Дать ему данные с двух бирок (переменные) и попросить его сравнить содержимое коробок, на которых они наклеены. Рассмотрим на примере.
Наш трудяга стремглав летит проверять, что у нас лежит в коробках с бирками name и same_name. А лежит у нас и там, и там одинаковая строка "Стэн". Оператор радостно нам сообщает об этом: True!
Закрепим - оператор "==" сравнивает переменные по значению (содержимое двух коробок с бирками, которые мы ему передали).
Ключевое слово "is"
Помимо работника, у нас в команде есть ключевое слово "is" (пускай на этот раз будет сотрудница). Умеет опять-таки немного, но работу свою выполняет чётко. Ей мы также даём информацию о том, что написано на двух бирках (названия переменных), а она проверяет, наклеены ли они на одну и ту же коробку (ссылаются ли переменные на одну и ту же ячейку памяти).
Рассмотрим на примере.
Из поста про переменные мы помним, что две одинаковые строки, которые мы кладем в две разные переменные, на самом деле будут лежать в одной и той же ячейке памяти, что и видно по адресу, который мы в обоих случаях вывели в консоль
То есть ещё раз: оператор "==" показывает, одинаковое ли значение (содержимое) хранится в двух ячейках памяти (коробках), на которые ссылаются две переменные (наклеены две бирки). Ключевое слово "is" показывает, ссылаются ли две переменные (наклеены ли две бирки) на одну и ту же ячейку памяти (коробку), или нет.
А зачем это вообще нужно?
Разве бывает так, чтобы ответы наших работников по поводу одинакового содержимого двух разных переменных различались?
Бывает. Рассмотрим на примере:
Несложно заметить, что во всех четырёх наших переменных в итоге окажется одна и та же строка (если мы честно ввели слово “Стэн” без кавычек, когда нас об этом попросили). Но в первых трех случаях эта строка оказалась в одной и той же ячейке, на которую “наклеились” три переменные:
Почему же в четвертом случае (для переменной
А вот то, что мы вводим с клавиатуры и передаем в переменную
Советую не верить мне на слово, а «пощупать» всё в PyCharm самостоятельно.
Ещё один пример
Итак, для чего нужен оператор "=="? Он позволяет проверить, совпадает ли содержимое двух коробок на складе (значения, хранящиеся в двух ячейках памяти). Он похож на работника склада, который умеет выполнять только эту задачу и никакую другую. Негусто, конечно, но зато справляется он со своей функцией на ура.
Как поставить работнику задачу? Дать ему данные с двух бирок (переменные) и попросить его сравнить содержимое коробок, на которых они наклеены. Рассмотрим на примере.
name = "Стэн"
same_name = "Стэн"
print(name == same_name)
Наш трудяга стремглав летит проверять, что у нас лежит в коробках с бирками name и same_name. А лежит у нас и там, и там одинаковая строка "Стэн". Оператор радостно нам сообщает об этом: True!
Закрепим - оператор "==" сравнивает переменные по значению (содержимое двух коробок с бирками, которые мы ему передали).
Ключевое слово "is"
Помимо работника, у нас в команде есть ключевое слово "is" (пускай на этот раз будет сотрудница). Умеет опять-таки немного, но работу свою выполняет чётко. Ей мы также даём информацию о том, что написано на двух бирках (названия переменных), а она проверяет, наклеены ли они на одну и ту же коробку (ссылаются ли переменные на одну и ту же ячейку памяти).
Рассмотрим на примере.
name = “Стэн"
print(id(name))
same_name = “Стэн"
print(id(same_name))
print(name == same_name)
print(name is same_name)
Из поста про переменные мы помним, что две одинаковые строки, которые мы кладем в две разные переменные, на самом деле будут лежать в одной и той же ячейке памяти, что и видно по адресу, который мы в обоих случаях вывели в консоль
print’ом. И нашей сотруднице это видно, о чём она нам и заявляет: True.То есть ещё раз: оператор "==" показывает, одинаковое ли значение (содержимое) хранится в двух ячейках памяти (коробках), на которые ссылаются две переменные (наклеены две бирки). Ключевое слово "is" показывает, ссылаются ли две переменные (наклеены ли две бирки) на одну и ту же ячейку памяти (коробку), или нет.
А зачем это вообще нужно?
Разве бывает так, чтобы ответы наших работников по поводу одинакового содержимого двух разных переменных различались?
Бывает. Рассмотрим на примере:
a = "Стэн"
b = "Стэн"
c = "Ст" + "эн"
d = input('Введите слово "Стэн": ') # Введем слово "Стэн" (без кавычек)
print(id(a)) # 4352025456
print(id(b)) # 4352025456
print(id(c)) # 4352025456
print(id(d)) # 4353014544
print(a == b) # True
print(a is b) # True
print(a == c) # True
print(a is c) # True
print(a == d) # True
print(a is d) # False
Несложно заметить, что во всех четырёх наших переменных в итоге окажется одна и та же строка (если мы честно ввели слово “Стэн” без кавычек, когда нас об этом попросили). Но в первых трех случаях эта строка оказалась в одной и той же ячейке, на которую “наклеились” три переменные:
a, b, c.Почему же в четвертом случае (для переменной
d) потребовалось новая ячейка в памяти? Всё дело в том, как Python пытается экономить память. На этапе компиляции кода он способен сравнивать строки между собой, а также проверять результат простых операций со строками (вроде конкатенации строк “Ст” и “эн”). Так как этот результат соответствует уже существующей в памяти строке “Стэн”, нам незачем создавать еще один такой же объект. Смело клеим бирку на уже созданную ранее коробку со Стэном. Процесс оптимизации работы со строками и некоторыми другими объектами называется “интернированием”, и мы когда-нибудь уделим ему отдельное внимание.А вот то, что мы вводим с клавиатуры и передаем в переменную
d, попадает в память уже в момент работы кода и поэтому для новой строки подбирается новая ячейка.Советую не верить мне на слово, а «пощупать» всё в PyCharm самостоятельно.
Ещё один пример
🔥4👍1
list_one = [1, 3, 5]Пройдёмся сверху вниз по коду примера:
list_two = [1, 3, 5]
list_three = list_one
list_four = list_one.copy()
print(id(list_one)) # 4509660416
print(id(list_two)) # 4511778176
print(id(list_three)) # 4509660416
print(id(list_four)) # 4510270528
print(list_one == list_two) # True
print(list_one is list_two) # False
print(list_one == list_three) # True
print(list_one is list_three) # True
print(list_one == list_four) # True
print(list_one is list_four) # False
1️⃣ Мы создали список из трех цифр и записали его в переменную
list_one.
2️⃣ Далее создали точно такой же список и записали его в переменную list_two.3️⃣ Затем на ячейку, к которой уже “прикреплена” переменная
list_one, "вешаем" еще одну переменную list_three.4️⃣ Наконец, в переменную
list_four записываем результат копирования списка из list_one.Первое, на что стоит обратить внимание,
list_one и list_two записались в разные ячейки памяти, что видно и по номерам этих ячеек, и по работе нашей прекрасной сотрудницы "is", которая выдает “False”, хотя её коллега "==" справедливо подтверждает, что содержатся в обеих переменных идентичные списки. Со строками из предыдущего примера в такой же ситуации результат, как мы помним, был другим. Да, такое поведение напрямую связано с особенностями этих типов данных, о чем мы подробно поговорим в следующий раз.Второе, на что стоит обратить внимание,
list_one и list_three “прицепились” к одной и той же ячейке. Это видно по работе функции id(), а также по показаниям наших сотрудников - "==" и "is".Третий важный момент: когда мы используем функцию
copy() для копирования списка, в переменную list_four попадает идентичный список с числами. Но записывается он уже в новую ячейку памяти, что легко видно по результатам работы id(), "==" и "is". Возможно, вы спросите, для чего вообще нужна эта манипуляция c copy(), если можно было бы, как и в случае с list_two, просто вручную пересоздать точно такой же список. Ну, хорошо, когда это можно сделать “на берегу” до запуска кода. А если список попадает к нам каким-то другим образом? Например, вводится через консоль или получается автоматически с какого-нибудь сайта? Если нам нужна точная его копия в другой ячейке памяти (а иногда это просто-таки необходимо), то copy() - один из возможных выходов из ситуации.Ну и последнее
list_one = [1, 3, 5]Работаем всё с теми же четырьмя переменными, в которых находится всё то же самое. К списку в
list_two = [1, 3, 5]
list_three = list_one
list_four = list_one.copy()
list_one.append(7)
print(list_one) # [1, 3, 5, 7]
print(list_two) # [1, 3, 5]
print(list_three) # [1, 3, 5, 7]
print(list_four) # [1, 3, 5]
list_one добавляем еще одно число и выводим в консоль все четыре переменные. Для тех, кто внимательно следил за ходом нашей мысли, не должно стать сюрпризом, что изменения, помимо списка в переменной list_one, коснулись и списка в переменной list_three. Почему? Потому что это один и тот же список, который “лежит” в одной и той же коробке, к которой мы прицепили две бирки: list_one и list_three. Списки из list_two и list_four остались нетронутыми, потому что каждый из них спокойно себе лежит в своей “коробке”.А вот если бы мы пытались проделать нечто подобное со строками или целыми числами, результат снова был бы отличным, но это уже совсем другая история…
Пост на сайте
Поддержать проект
#Python #код_в_мешке #переменные #управление_памятью #операторы #ключевые_слова #is #оператор_сравнения
🔥5
Django 36. Добавление постов пользователем
Автор: Иван Ашихмин
Продолжаем развивать наш блог. Мы с вами реализовали регистрацию и создали профиль пользователя, теперь реализуем добавление постов не только Администратором, но и Авторами.
Создать форму для добавления постов, создания новых категорий или загрузки файлов - задача нехитрая. Куда сложнее дать авторам возможность редактировать и при необходимости удалять уже созданные ими ранее посты.
В этом и нескольких последующих постах мы подробно рассмотрим процесс создания страницы с формами, а также приспособим личный кабинет под нужды авторов.
Библиотека pytils.
Автор: Иван Ашихмин
Продолжаем развивать наш блог. Мы с вами реализовали регистрацию и создали профиль пользователя, теперь реализуем добавление постов не только Администратором, но и Авторами.
Создать форму для добавления постов, создания новых категорий или загрузки файлов - задача нехитрая. Куда сложнее дать авторам возможность редактировать и при необходимости удалять уже созданные ими ранее посты.
В этом и нескольких последующих постах мы подробно рассмотрим процесс создания страницы с формами, а также приспособим личный кабинет под нужды авторов.
Библиотека pytils.
В модели поста есть поле
Когда мы добавляем пост через панель администратора, его заголовок преобразуется в текст на латинице автоматически.
В случае с добавлением поста на стороне сайта такой возможности нет, поэтому мы прибегнем к помощи библиотеки pytils, в которой есть функция slugify, переводящая текст из кириллицы в латиницу.
Установим библиотеку командой:
И добавим её в
Группа пользователей "Автор".
Для того, чтобы создавать посты могли только авторы, а не все пользователи, необходимо создать такую группу в панели администратора.
Откроем панель администратора и в блоке "Пользователи и группы" откроем раздел Группы.
Нажимаем кнопку "Добавить".
В поле "Имя" вводим название группы, в нашем случае - "Автор".
На данный момент никакие права не выдаём, нам нужна только группа пользователей.
Нажимаем "Сохранить".
Готово. Теперь у нас есть группа "Авторы".
Для добавления пользователя в эту группу необходимо открыть раздел "Пользователи", выбрать нужного пользователя и в блоке с выбором группы добавить группу "Автор" в выбранные.
Форма добавления поста.
Нам нужно создать форму модели для добавления нового поста.
Откроем файл
Ранее мы прописывали каждое поле с его типом и виджетом. В этот раз мы поступим иначе: получим поля из модели и в конструкторе класса
После цикла, дополнительно пропишем полю "категория" ещё один класс для выпадающих списков.
Для тех, кто использует django-ckeditor5:
С использованием данного редактора вне панели администратора есть забавная особенность.
Дело в том, что поле с редактором в модели обязательно к заполнению, но если оставить поле формы обязательным, то форма не будет работать. JavaScript редактора самостоятельно обрабатывает ввод, а исходное поле формы скрывается. В результате получается так, что данные в редакторе есть, а в поле формы при этом ничего не введено. В связи с этим браузер не отправляет форму на сервер, считая, что форма не заполнена.
Для решения этой проблемы достаточно в форме указать, что она необязательна к заполнению, при этом в модели убирать обязательность не нужно. Если будет отправлена форма с пустым полем, то страница просто обновится и укажет на ошибку.
В
И прописываем стандартный внутренний класс
Код формы:
slug. Подробнее о нём я писал в постах "Django 16. Модель категорий" и "Django 20. Модель поста".Когда мы добавляем пост через панель администратора, его заголовок преобразуется в текст на латинице автоматически.
В случае с добавлением поста на стороне сайта такой возможности нет, поэтому мы прибегнем к помощи библиотеки pytils, в которой есть функция slugify, переводящая текст из кириллицы в латиницу.
Установим библиотеку командой:
pip install pytils
И добавим её в
requirements.txt:pytils~=0.4.1
Группа пользователей "Автор".
Для того, чтобы создавать посты могли только авторы, а не все пользователи, необходимо создать такую группу в панели администратора.
Откроем панель администратора и в блоке "Пользователи и группы" откроем раздел Группы.
Нажимаем кнопку "Добавить".
В поле "Имя" вводим название группы, в нашем случае - "Автор".
На данный момент никакие права не выдаём, нам нужна только группа пользователей.
Нажимаем "Сохранить".
Готово. Теперь у нас есть группа "Авторы".
Для добавления пользователя в эту группу необходимо открыть раздел "Пользователи", выбрать нужного пользователя и в блоке с выбором группы добавить группу "Автор" в выбранные.
Форма добавления поста.
Нам нужно создать форму модели для добавления нового поста.
Откроем файл
forms.py в приложении user_app. Создадим новый класс AddPostByAuthorForm, унаследованный от forms.ModelForm.Ранее мы прописывали каждое поле с его типом и виджетом. В этот раз мы поступим иначе: получим поля из модели и в конструкторе класса
__init__ проитерируемся по списку полей, добавляя к атрибутам поля нужный bootstrap-класс.После цикла, дополнительно пропишем полю "категория" ещё один класс для выпадающих списков.
Для тех, кто использует django-ckeditor5:
С использованием данного редактора вне панели администратора есть забавная особенность.
Дело в том, что поле с редактором в модели обязательно к заполнению, но если оставить поле формы обязательным, то форма не будет работать. JavaScript редактора самостоятельно обрабатывает ввод, а исходное поле формы скрывается. В результате получается так, что данные в редакторе есть, а в поле формы при этом ничего не введено. В связи с этим браузер не отправляет форму на сервер, считая, что форма не заполнена.
Для решения этой проблемы достаточно в форме указать, что она необязательна к заполнению, при этом в модели убирать обязательность не нужно. Если будет отправлена форма с пустым полем, то страница просто обновится и укажет на ошибку.
В
__init__ указываем класс редактора и то, что поле не обязательно.И прописываем стандартный внутренний класс
Meta с указанием на модель и перечислением полей.Код формы:
from blog.models import PostModel
class AddPostByAuthorForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].widget.attrs.update({'class': 'form-control', 'autofocus': ''})
self.fields['short_body'].widget.attrs.update({'class': 'django_ckeditor_5'})
self.fields['full_body'].widget.attrs.update({'class': 'django_ckeditor_5'})
self.fields['category'].widget.attrs.update({'class': 'form-select'})
self.fields["short_body"].required = False
self.fields["full_body"].required = False
class Meta:
model = PostModel
fields = ('title', 'image', 'category', 'short_body', 'full_body', 'status', 'telegram_link',
'file', 'tags', 'telegram_body')
Представление страницы добавления поста.
Откроем файл
views.py.Создадим класс
AddPostByAuthorView, унаследованный от двух классов: UserPassesTestMixin и CreateView.UserPassesTestMixin - это класс в Django, предоставляющий удобный способ ограничения доступа к представлениям на основе пользовательских тестов. Он позволяет определить метод test_func, который выполняет проверку и возвращает True, если пользователь должен иметь доступ, или False, если доступ следует отклонить. Если пользователь не проходит тест, то он перенаправляется на страницу, указанную в login_url.В классе пропишем три знакомых нам поля:
template_name, form_class и model.Также три метода:
test_func - в этом методе мы проверяем, что пользователь состоит в группе "Автор". Если пользователь в ней не состоит, то страница добавления поста не откроется.get_success_url - указываем на какую страницу перенаправить пользователя после добавления поста.form_valid - метод, проверяющий валидность формы. В нашем случае мы в ней заполняем два отсутствующих в форме поля: author и slug.Код представления:
from django.contrib.auth.mixins import UserPassesTestMixin
from django.views.generic import CreateView
from pytils.translit import slugify
from blog.models import PostModel
from user_app import forms
class AddPostByAuthorView(UserPassesTestMixin, CreateView):
template_name = 'user_app/add_post.html'
form_class = forms.AddPostByAuthorForm
model = PostModel
def test_func(self):
return self.request.user.groups.filter(name='Автор').exists()
def get_success_url(self):
return reverse('user_app:user_profile', kwargs={'username': self.request.user.username})
def form_valid(self, form):
form.instance.slug = slugify(form.instance.title)
form.instance.author = self.request.user
return super().form_valid(form)
URL-паттерн страницы добавления поста.
Откроем файл
urls.py и в список urlpatterns добавим следующую строку:path('post/add_post/', views.AddPostByAuthorView.as_view(), name='add_post'),Кнопка перехода на страницу добавления поста.
Я решил расположить кнопку в меню пользователя в шапке сайта.
Откроем файл
header.html и в блоке авторизованного пользователя добавим проверку на наличие в группе "Автор" и саму кнопку, если он там есть:{% if "Автор" in user.groups.all.0.name %}
<li>
<a class="dropdown-item dd-item-color" href="{% url 'user_app:add_post' %}">Добавить
пост</a>
</li>
{% endif %}Шаблон страницы добавления поста.
В директории с шаблонами приложения
В целом это обычная форма, за исключением одного момента.
Если вы используете
Код шаблона:
В следующем посте сделаем формы добавления категории и файлов.
Файлы к посту, можно получить в боте по коду: 517311
Пост на сайте
Поддержать проект
#Python #Django #модели #формы #представления #гайды #slugify #pytils #группы_пользователей #ckeditor #django_ckeditor #slug
В директории с шаблонами приложения
user_app создадим файл add_post.html.В целом это обычная форма, за исключением одного момента.
Если вы используете
django-ckeditor5, то помимо стандартных csrf_token и form.as_p, необходимо добавить form.media. Без этого редактор не будет отображаться.Код шаблона:
{% extends 'blog/base.html' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container mt-3 d-flex justify-content-center">
<div class="col-lg-8 col-sm-12">
<h2>Добавление поста</h2>
<form method="post" enctype="multipart/form-data" action="{% url 'user_app:add_post' %}">
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button type="submit" class="btn btn-success mt-3">Сохранить</button>
</form>
</div>
</div>
{% endblock %}
Готово. Теперь авторы могут добавлять посты.В следующем посте сделаем формы добавления категории и файлов.
Файлы к посту, можно получить в боте по коду: 517311
Пост на сайте
Поддержать проект
#Python #Django #модели #формы #представления #гайды #slugify #pytils #группы_пользователей #ckeditor #django_ckeditor #slug