Код на салфетке
2.22K subscribers
748 photos
15 videos
2 files
791 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
Чтобы исправить это, в окне "Webview", в адресной строке нажимаем кнопку "New tab". Сайт откроется в новой вкладке. Копируем из адресной строки адрес сайт, он будет выглядеть примерно так: https://351b1912-c31d-4b10-a236-e7b8046a752d-00-3ll5ep3cujefu.picard.replit.dev/

Открываем файл settings.py и добавляем его в ALLOWED_HOSTS:
ALLOWED_HOSTS = ["127.0.0.1", "351b1912-c31d-4b10-a236-e7b8046a752d-00-3ll5ep3cujefu.picard.replit.dev"]


Сайт автоматически перезагрузится и в окне Webview отобразится главная страница.

На этом разворачивание сайта закончено.


Настройка статики.
Поскольку в Replit нет стороннего веб-сервера, статику должна отдавать сама Django. Для этого откроем файл settings.py и изменим настройки статических файлов:
STATIC_URL = "static/"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]



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

Лично мне, Replit нравится значительно больше, чем PythonAnyWhere, как минимум из-за скорости работы и простоты настройки.

Пост на сайте
Поддержать проект

#Python #Django #Гайды #Deploy #бесплатный_хостинг #replit #разворачивание
🔥6
Поздравление с 8-м марта!
Авторы: Иван Ашихмин, Андрей Лебедев, Артур Мурзыев

Всемирный женский день - самый милый праздник в году. И это действительно так! Женщины, девушки, дамы украшают своим присутствием всё: семьи, группы, коллективы. И наш коллектив не исключение.

По статистике на женщин в российском it-секторе приходится примерно треть общего кадрового состава. И даже в наших микроскопических коллективах – редакции «Кода на салфетке» и команде «Некоего проекта» – эта доля плюс-минус соблюдается: в первом девушек у нас четверть, а во втором – 31%. Но и в том, и в другом случае цифры не должны вводить в заблуждение. Девочки у нас действительно в меньшинстве, но это активное, живое и надежное меньшинство, на котором держатся оба проекта.
🎉6👏21
Наш проджект-менеджер Кристина - самый активный, обязательный, понимающий и ответственный человек в нашей команде. Она никогда не прибегает к угрозам и не повышает тон, но при этом мало кто позволяет себе её ослушаться. А если кто-нибудь все-таки осмелится, Кристина мягко, но настойчиво напомнит о том, как нужно себя вести.

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

Женя - наш единственный аналитик. Тут и добавить нечего, она совершенно незаменима. В команде «Некоего проекта» все делают вид, что понимают, как и куда нужно двигаться и развиваться, но только Женя сможет компетентно и, опираясь на факты, аргументировать, почему она права. Кроме того, в Жене впечатляет её упорство и трудолюбие: она внимательнейшим образом изучает всё, что попадает к ней в руки, неустанно работает и всегда добирается до истины.

Наташа присоединилась к команде фронтов «Некоего проекта» и с ходу стала её мотором. Не пропустила ни одного созвона, уже успела несколько раз проявить себя и завоевать симпатии местного лида.

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

Пост на сайте

#Код_на_салфетке #Некий_проект #поздравление #8_марта
6🔥3🎉3🥰1🍾1
Добрый вечер, дорогие друзья!

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

Фильм: Запрещённый приём

Год: 2011

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

https://www.sspoisk.ru/film/429827/

Приятного просмотра
🔥4👍2
Что выведет код с изображения ниже? №13
Anonymous Quiz
60%
Hello World
5%
HelloWorld
18%
Hello
18%
Ничего из перечисленного выше
Что выведет этот код? №13
Продолжая тему ошибок, начатую в задаче №12, вчера мы опубликовали задачу №13, суть которой заключалась в обработке исключений, а именно в работе блока try-ecxept-else-finally. Задачу решило 30 человек, это 58% из 52 человек.


Код задачи:
def func():
try:
print("Hello", end=' ')
return
finally:
print("World")


func()



Разберём задачу.
Создаём функцию func.

В теле функции создаём try-finally конструкцию.

Внутри блока try выводим в терминал слово "Hello", заменив перенос строки на пробел. Затем производим "выход" из функции вызвав return.

В блоке finally выводим в терминал слово "World".

Вызываем функцию func.


Hello World!
Именно так, в ответ на роботу программы, мы получили "Hello World", но как так получилось, если мы использовали return, спросите вы?
Ответ прост: блок finally срабатывает всегда, независимо от того, выпала ли ошибка и был ли сделан выход из функции. Исключение – разве что остановка программы, но это уже совершенно другой класс ошибок.

Давайте поподробнее разберёмся в структуре try-except и в том, как всё работает.

Обработка исключений try в Python состоит из четырёх блоков:
1. try – в этот блок записывается выражение или действие, которое может вызвать исключение.
2. except – в этом блоке располагаются "отлавливаемые" исключения. Он срабатывает, если в блоке try было поднято исключение.
3. else – в этот блок записываются действия, выполняемые в случае, если в блоке try не произошло исключения.
4. finally – этот блок выполняется при любом исходе. Выполнится ли try без ошибок, или будет поднято исключение, – неважно. Блок выполняется всегда.

Пример try-except-else без ошибки:
try:
result = 3 / 2
except ZeroDivisionError:
print("Сработало исключение!")
else:
print(f"Результат: {result}")

>>> Результат 1.5


В блоке try делим одно число на другое.
В блоке except пытаемся поймать ошибку деления на ноль, если она будет вызвана.
В блоке else выводим результат.

Пример try-except-finally с ошибкой:
try:
result = 3 / 0
except ZeroDivisionError:
return 0
finally:
print(f"Звоните в поддержку! У нас ошибка!")

>>> Звоните в поддержку! У нас ошибка!


В блоке try делим одно число на другое. Намеренно вызываем ошибку деления на ноль.
В блоке except ловим ошибку деления на ноль и делаем возврат 0.
В блоке finally выводим в терминал сообщение о том, что сработала ошибка.

Заключение.
Правильная обработка исключений – залог отсутствия ошибок, хорошей читаемости и надёжной работы кода.
Python предлагает гибкую систему обработки исключений. Благодаря тому, что блоки else-finally не являются обязательными, их можно добавлять по ситуации. Один из ярких примеров – запуск Telegram-бота в блоке try-finally. В блоке try запускается обработчик сообщений с сервера, но если по какой-то причине бот будет остановлен, сработает блок finally, который, например, оповестит администратора об остановке бота.
🔥7👍1🗿1
Всем привет!

Сегодня в 18 часов (по МСК) на YouTube-канале будет стрим.

На стриме продолжим разрабатывать бота. Что-то починим, что до добавим.

Приходите, задавайте вопросы в чате, общайтесь 🙂

Ссылка на канал: https://www.youtube.com/@codeonanapkin
🔥3
Всем доброго утра)

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

Ещё одной неприятностью стало то, что на стриме играла музыка с ютуба и я всё равно словил страйк за авторские права, пришлось удалить 2 минуты из видео, думаю не страшно)

Запись стрима: https://www.youtube.com/watch?v=Bwr_aNfU1Qg&t=401s
Также залил все изменения в репозиторий.
🔥2👍1
Удобное время для стрима в воскресенье?
Anonymous Poll
26%
12-13
12%
14-15
15%
16-17
47%
18
🔥1😁1
ООП на Python. ч. 2. Статические методы
Автор: Андрей Лебедев

Продолжаем цикл постов об ООП на Python. В прошлый раз мы говорили об ООП как таковом, об объекте self и о методе __init__. На сей раз мы поведем речь о методах классов. И начнём мы со статических и классовых методов.

Что такое статический метод?

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

Всем ли методам класса нужен объект self?
🔥5👍3
После нашего первого поста вы могли подумать, что объект self необходимо передавать в качестве аргумента всем без исключения методам класса. Но если в методе никак не используется ни сам этот объект, ни какой-либо из его атрибутов, зачем тогда этот объект туда передавать? Метод прекрасно справится со своей задачей и без self.

Представим, что у нас есть класс, описывающий марку сигарет:


class Cigarette:

def __init__(self, name="", nicotine_amount=0.0):
self.name = name
self.nicotine_amount = nicotine_amount

def describe_cigarette(self):
message = f'В сигаретах марки "{self.name}" содержится {self.nicotine_amount:} мг никотина.'
print(message)


my_cigarette = Cigarette("Ява", 0.8)
my_cigarette.describe_cigarette()


Мы описали класс, объект которого – марка сигарет. При инициализации объекта указывается название марки и содержание никотина в миллиграммах на сигарету. Единственный метод этого класса, не считая __init__, – describe_cigarette выводит в консоль сообщение о содержании никотина в сигаретах данной марки.

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


class Cigarette:

def __init__(self, name="", nicotine_amount=0.0):
self.name = name
self.nicotine_amount = nicotine_amount

def describe_cigarette(self):
message = f'В сигаретах марки "{self.name}" содержится {self.nicotine_amount:} мг никотина.'
print(message)

def show_disclaimer(self):
message = 'Курение вредит вашему здоровью.'
print(message)


my_cigarette = Cigarette("Ява", 0.8)
my_cigarette.describe_cigarette()
my_cigarette.show_disclaimer()


В результате работы нашего кода одно за другим выведутся два сообщения: о содержании никотина в сигаретах марки “Ява” и о вреде курения.
Как и всегда, мы добавили объект self в качестве аргумента во вновь созданный нами метод show_disclaimer. При этом важно заметить, что ни сам этот объект self, ни его атрибуты никак в методе не задействованы. И это диктуется самим смыслом выводимого предупреждения о вреде курения: оно одинаково для любой марки сигарет.

Избавимся от self

Если мы просто возьмём и выбросим из кода ненужный нам аргумент self из метода show_disclaimer, выполнение кода завершится следующим исключением:


TypeError: Cigarette.show_disclaimer() takes 0 positional arguments but 1 was given


Суть ошибки в том, что наш метод теперь не принимает никаких аргументов, но Python автоматически передает self в каждый метод класса Cigarette.

Статические методы

Методы, которые не используют данные конкретного объекта (то есть его атрибуты), встречаются довольно часто. И когда это происходит, нет никакой необходимости передавать в них лишнюю ссылку на объект self. Чтобы этого не делать, необходимо перед методом вставить декоратор @staticmethod:


class Cigarette:
def __init__(self, name="", nicotine_amount=0.0):
self.name = name
self.nicotine_amount = nicotine_amount

def describe_cigarette(self):
message = f'В сигаретах марки "{self.name}" содержится {self.nicotine_amount:} мг никотина.'
print(message)

@staticmethod
def show_disclaimer():
message = 'Курение вредит вашему здоровью.'
print(message)


my_cigarette = Cigarette("Ява", 0.8)
my_cigarette.describe_cigarette()
my_cigarette.show_disclaimer()


Вывод у этого кода будет точно таким же, как в предыдущем случае с self.
🔥4👍3
Благодаря тому, что работа статических методов никак не связана с информацией о конкретном объекте, вызывать их можно прямо из класса, не создавая при этом объект. Для этого достаточно указать название класса и сам статический метод через точечную нотацию:


Cigarette.show_disclaimer()


В такой версии код выведет на печать только само предупреждение о вреде курения.

Для чего использовать статические методы?

А в чем вообще смысл этого действия? Почему нельзя просто вставлять ссылку на self в качестве аргумента во все методы, даже если сам объект не будет в итоге использован? Здесь можно выделить два важных для понимания момента:

Классы, в которых статические методы выделены надлежащим образом, понятнее для восприятия. Когда вы выделяете тот или иной метод декоратором @staticmethod, вы не только подсказываете Python’у, как ему работать с этим методом. Вы также посылаете сигнал другим разработчикам о том, что этот метод не меняет ничего в самом объекте, а доступ к нему можно получить, не создавая объектов класса вообще.

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


Футбольный клуб

Напишем класс для футбольного клуба:


class FootballClub:

def __init__(self, name, description=""):
self.name = name
self.description = description

def describe_club(self):
msg = f"{self.name}: {self.description}"
print(msg)


tree = FootballClub("Манчестер Юнайтед")
tree.description = "Манчестер, Англия"
tree.describe_tree()


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


Манчестер Юнайтед: Манчестер, Англия


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

Футбольная лига

Допустим, нам нужно создать футбольную лигу. Добавим в неё ещё пару клубов, используя тот же класс:


clubs = []

club = FootballClub("Манчестер Юнайтед")
club.description = "Манчестер, Англия"
clubs.append(club)

club = FootballClub("Реал")
club.description = "Мадрид, Испания"
clubs.append(club)

club = FootballClub("Ювентус")
club.description = "Турин, Италия"
clubs.append(club)

for club in clubs:
club.describe_club()


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


Манчестер Юнайтед: Манчестер, Англия
Реал: Мадрид, Испания
Ювентус: Турин, Италия


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

class FootballClub:
num_clubs = 0

@classmethod
def count_clubs(cls):
msg = f"Клубов в нашей лиге: {cls.num_clubs}."
print(msg)

def __init__(self, name, description=""):
self.name = name
self.description = description

FootballClub.num_clubs += 1

def describe_club(self):
msg = f"{self.name}: {self.description}"
print(msg)


clubs = []

club = FootballClub("Манчестер Юнайтед")
club.description = "Манчестер, Англия"
clubs.append(club)

club = FootballClub("Реал")
club.description = "Мадрид, Испания"
clubs.append(club)

club = FootballClub("Ювентус")
club.description = "Турин, Италия"
clubs.append(club)

for club in clubs:
club.describe_club()

FootballClub.count_clubs()


Сначала вне метода __init__ создадим атрибут класса num_clubs. Обратим внимание, что никакой приставки в виде self перед этим атрибутом у нас нет, потому что он связан не с экземпляром класса, а с классом в целом.
Далее пишем классовый метод, предварив его декоратором @classmethod. При помощи этого декоратора в метод передается весь класс. По умолчанию в классовых методах сам класс обозначается параметром cls. Внутри самого метода доступ к атрибуту класса можно получить через точечную нотацию. Так, к числу клубов в нашей лиги мы получаем доступ следующим образом: cls.num_clubs.

Чтобы количество клубов всегда было актуальным, при создании каждого нового экземпляра класса нам нужно увеличивать число, записанное в num_clubs, на единицу. Мы сделали это в методе __init__:


def __init__(self, name, description=""):
self.name = name
self.description = description

FootballClub.num_clubs += 1


Так как метод __init__ не принимает cls в качестве аргумента, доступ к атрибуту num_clubs мы получаем через название класса.

В конце мы вызываем метод класса, снова обратившись к нему по названию:


FootballClub.count_clubs()


Вывод будем следующим:


Манчестер Юнайтед: Манчестер, Англия
Реал: Мадрид, Испания
Ювентус: Турин, Италия
Клубов в нашей лиге: 3.


Обращаться к атрибутам класса и классовым методам можно несколькими способами, не только так, как мы показали выше.

Доступ к атрибуту класса по названию класса

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


@classmethod
def count_clubs(cls):
msg = f"Клубов в нашей лиге: {FootballClub.num_clubs}."
print(msg)


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

Вызов классового метода из экземпляра класса

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


club = FootballClub("Манчестер Юнайтед")
club.description = "Манчестер, Англия"
club.count_clubs()


Результат будет таким же, как и в случае с FootballClub.count_clubs().

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

Подобная гибкость облегчает работу, поскольку разработчику необязательно думать о том, что происходит под капотом в том или ином классе. Можно просто пользоваться результатами труда тех, кто разработал и поддерживает саму библиотеку.

Доступ к атрибуту класса из обычного метода класса
🔥5
Атрибутами класса можно пользоваться и в обычных методах класса. Например, если нам нужно расширить описание футбольного клуба, включив в него информацию о количестве команд в его лиге:


def describe_club(self):
msg = (f"{self.name}: {self.description}\n"
f"Клубов в лиге: {FootballClub.num_clubs}")
print(msg)


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

Можно ли получить доступ к атрибутам класса через self?

Ответ: да, можно. Если во всём классе у нас есть только один атрибут с данным именем, то ошибки не будет:


def describe_club(self):
msg = (f"{self.name}: {self.description}\n"
f"Клубов в лиге: {self.num_clubs}")
print(msg)


Этот код будет работать так же, как и код из примера выше.

На что обращать внимание?

Сложности начинаются при попытке записать новое значение в атрибут класса с помощью объекта self. Дело в том, что, используя self, вы создаете новый атрибут именно экземпляра, если такой атрибут не был создан ранее. В такой редакции код не будет давать нам искомый результат:


class FootballClub:
num_clubs = 0

@classmethod
def count_clubs(cls):
msg = f"Клубов в нашей лиге: {cls.num_clubs}."
print(msg)

def __init__(self, name, description=""):
self.name = name
self.description = description

self.num_clubs += 1

def describe_club(self):
msg = (f"{self.name}: {self.description}\n"
f"Клубов в лиге: {self.num_clubs}")
print(msg)


Мы, как и раньше, увеличиваем число клубов на единицу, когда инициализируем новый объект класса. Но так как теперь мы делаем это через объект self, а не через название класса, мы не меняем атрибут класса num_clubs, а создаём новый атрибут экземпляра с таким же точно названием. И теперь у нас два атрибута с одинаковым названием num_clubs: один относится к классу, а другой - к конкретному его экземпляру. И вывод у кода будет следующий:


Манчестер Юнайтед: Манчестер, Англия
Клубов в лиге: 1
Реал: Мадрид, Испания
Клубов в лиге: 1
Ювентус: Турин, Италия
Клубов в лиге: 1
Клубов в нашей лиге: 0.


В атрибуте num_clubs каждого экземпляра класса теперь записано по единице, но атрибут num_clubs класса так и не изменился: это по-прежнему ноль. Если логика в этом случае не очень понятно, можно просто запомнить важный вывод. Работая с атрибутом класса внутри самого класса, всегда используйте cls, если речь о классовом методе, и название класса, если речь об обычном методе. И постарайтесь не создавать атрибутов класса и атрибутов экземпляра с одинаковым названием.

В следующий раз поговорим о методах __str__ и __repr__.

Пост на сайте
Поддержать проект

#Python #ООП #код_в_мешке #объект #атрибут #класс #init #self #метод
🔥9
В воскресенье в 18:00 состоится третий стрим.

Продолжаем делать Telegram-бота для управления VPSкой.

Что мы уже сделали:
- Выполнение произвольной команды с выводом результата.
- Выполнение последовательности команд с запоминанием изменения пути при использовании команды cd.
- Оповещение администратора о запуске-остановке бота и меню.
- Меню управления Docker-контейнерами.

Что ещё в планах:
- Сделать вывод используемых сервером ресурсов (ОЗУ, ЦПУ).
- Сделать меню с избранными командами. Для реализации необходимо подключить БД используя SQLAlchemy.
- Сделать обработку сообщений только от администратора.

Если у вас есть ещё идеи - пишите в комментариях!

Всех жду Воскресенье 18:00: https://www.youtube.com/@codeonanapkin

P.S. Всем, кто поддерживает канал на Boosty доступен репозиторий с исходным кодом проекта.
👍3🔥1
Доброго пятничного вечера, Друзья!

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

Фильм: Оппенгеймер

Год: 2023

История физика-теоретика Джулиуса Роберта Оппенгеймера, считающегося «отцом атомной бомбы». В 1940-х годах в рамках «Манхэттенского проекта» он руководил разработкой первого ядерного оружия в Лос-Аламосской национальной лаборатории. «Оппенгеймер» (2023) — биографическая драма Кристофера Нолана с Киллианом Мерфи в главной роли, основанная на книге «Американский Прометей: Триумф и трагедия Дж. Роберта Оппенгеймера» Кая Берда и Мартина Дж. Шервина.

https://www.sspoisk.ru/film/4664634/

Приятного просмотра
🔥5👍1
Что выведет код с изображения ниже? №14
Anonymous Quiz
29%
0
7%
1
39%
3
24%
AttributeError
🔥3
Что выведет этот код? №14
🔥3
Код на салфетке
ООП на Python. ч. 2. Статические методы Автор: Андрей Лебедев Продолжаем цикл постов об ООП на Python. В прошлый раз мы говорили об ООП как таковом, об объекте self и о методе __init__. На сей раз мы поведем речь о методах классов. И начнём мы со статических…
Вчера мы опубликовали задачу №14, которая является закреплением темы, начатой в посте "ООП на Python. ч. 2. Статические методы". С задачей справилось всего 7 человек из 26...

Код задачи:
class PopSinger:
num_singers = 0

@classmethod
def count_singers(cls):
msg = f"Певцов на нашем концерте: {cls.num_singers}."
print(msg)

def __init__(self, name, description=""):
self.name = name
self.description = description

self.num_singers += 1


klava = PopSinger("Клава Кока", "27 лет, женщина")
insta = PopSinger("Инстасамка", "23 года, женщина")
feduk = PopSinger("Федук", "32 года, мужчина")

PopSinger.count_singers()


Разбор задачи.
Привычного разбора задачи не будет, поскольку задача повторяет описанное в посте. Если вы не читали пост "ООП на Python. ч. 2. Статические методы", то настоятельно рекомендую это сделать, как минимум чтобы закрыть пробел в понимании работы методов класса.
🔥4