Кодим вместе: Путь к IT-Успеху
530 subscribers
112 photos
1 video
104 links
🌟Всем привет! Я начинающий Python-разработчик, вернувшийся к обучению. Здесь делюсь своими планами и достижениями, чтобы мотивировать вас и себя заниматься программированием каждый день! 🚀
Download Telegram
🔐 Режимы доступа: public, private, protected. Сеттеры и геттеры

Это последняя пройденная тема. Коротко об этом. Есть три типа доступа для атрибутов/свойств и методов класса/экземпляра класса:

📌 attribute (без подчёркиваний) - публичное свойство (public)
📌 _attribute (с одним подчёркиванием) - protected (внутри класса и дочерних классов)
📌 __attribute (с двумя подчёркиваниями) - private (только внутри класса)

🤔 Формально 3, но фактически 2

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

😁 Но есть одно но

Если очень хочется, то можно))

Допустим у нас есть класс User. Мы создали экземпляр класса, в init-e прописав его возраст(__age) как приватную(private) переменную:
u = User(27)

Можно обратиться к атрибуту __age так:
u._User__age

А если напрямую через u.age или u.__age - будет ошибка. Но вообще лучше так не делать)

🛠 Сеттеры и геттеры

Это просто такие методы в классе, которые что-то делают с приватными атрибутами:
📌 set_age(self, age) - изменить значение возраста
📌 get_age(self) - вернуть значение возраста

Методы класса так же могут иметь разные режимы доступа.

💬 Есть вопросы или хотите поделиться опытом?
Присоединяйтесь к обсуждению в чате!
5
😶😶😶Связные списки 👿👿👿

Не люблю я эти связные списки... А тут еще и двунаправленные! 🫠

Было так:
- Накидал код → отошел → вернулся → снова ничего не понял 🫡
- Немного подсмотрел решение, не до конца → ничего нового не узнал, закрыл видео😁
- Пошел дальше делать... но не получилось до конца!

Пришлось достать "тяжелую артиллерию" — старый дедовский метод с тетрадкой! 📝
Начал расписывать вручную: что, куда, зачем и почему. Давно так не запаривался!

А вот и главным врагом неожиданно оказался метод `remove()`
Думал: "ну удаление, что сложного?"
А оказалось:
- Целых три случая удаления!
- Общий случай не проходил
- Пришлось звать на помощь ИИ 🆘

🤔 А вам как дались связные списки?
- Было так же сложно?
- Или для вас это было просто?
- Есть свои лайфхаки для понимания?

P.S.
Вот ссылка на теорию по этой теме: урок
Надеюсь, таких задач больше не встретится! А то я еще неделю буду сниться сам себе с указателями next-prev 🔁

💬 Делитесь опытом в чате — интересно узнать ваши истории!
😱3
😵‍💫 Застрял в режиме "Лебедь, рак и щука"

Последние две недели сильно просел объем занятий. Причина — на фото 👆

Как вы помните, я говорил, что не собираюсь разветвляться и уходить в другие направления. План простой:
- Завершить курс по Базе, ООП, Django
- Подтянуть требования из вакансий
- Искать работу

Но не знаю, почему именно сейчас мне в голову взбрело создание задач! 🤷‍♂️ Создаю задачки по разным темам — по сути, та же рубрика "викторина", но местами сложнее.

Выходит:

- Это отнимает **много времени и сил
- После 3 дней плотной работы + курс по ООП — полный выгорание
- Не хотелось возвращаться вообще ни к чему

Об этом и был мой последний пост про отдых в 3-4 дня — просто без конкретных причин.

Чувствую, что это меня сильно тормозит, но и отказываться не хочется...

Как в басне Крылова 🦢🦀🦐
И то хочу, и это, и пятое-десятое.
А по факту — "А воз и ныне там" 😮‍💨

Как вам удавалось бороться с таким распылением? Или я один такой?)

💬 Буду рад вашим советам в чате — как вы удерживаете фокус?
👀4
Сегодня же Хэллоуин. Празднуете?

А может кто-то еще нарядился и накрасился, есть такие?) Скидывайте фотки кто в каком образе находится, будет интересно посмотреть😈
😈3
Интересная задачка дня

Условие, тесты

Вспоминаем match-case. 🫣

Вводятся данные по книге в виде строки через запятую в формате (некоторые значения могут отсутствовать):
id, автор, название, цена, год издания с помощью команд:
t = (int, str, str, float, int)
book = [t[i](x) if t[i] != str else x.strip() for i, x in enumerate(input().split(","))]


С помощью оператора match/case необходимо определить шаблоны для выделения следующей информации с дополнительными проверками:

• автор, название (автор - не менее 6 символов, название - не менее 10 символов)
• автор, название, цена (автор не менее 6 символов, цена - положительное число)
• автор, название, год издания (год издания от 2020 и выше)
• автор, название, цена, год издания (цена - положительное число и год издания от 2020 и выше)

Первый шаблон срабатывает, если есть только автор и название; второй, если появляется еще и цена; третий, если есть автор, название, год издания, но нет цены; последний, если имеются все данные.

При срабатывании шаблона вывести на экран строку "Yes". Если ни один из шаблонов не сработал, то вывести строку "No"

💬 Присылайте свои варианты решений. 😏

Я чет глянул как сам делал - уже не особо помню всю логику конструкции.😢 Ужс, как vsё быстро забывается, если это редко используешь.
🤔3
Викторина. Что выведет код ?
Cмотрите в комментарий под постом
Anonymous Quiz
6%
Ошибку
42%
Ключ не определен
36%
Ключ не подходит
17%
Ключ подходит
🤔3
привет, кое-что нашел для вас ⤵️
💙🛠 Kickresume.com/en/ats-resume-checker/ ATS-чекер для вашего резюме


-- Бесплатно даст оценку (0-100) и покажет, по каким категориям (Дизайн, Структура, Содержание) у вас провал.

--Загружайте, правьте, перезагружайте резюме. Следите, как растет ваш балл после каждого изменения. Это главный лайфхак.

--Сравнивайте с резюме из топ-компаний. У них есть реальные примеры - смотрите, как структурируют опыт другие.

⚡️ Краткий план действий:

Выберите ATS-дружественный шаблон (есть в самом Kickresume).

Пройдите бесплатную проверку.

Исправьте всё, что подсветилось красным.

Повторите пункты 2 и 3, пока не получите 80+ баллов.

Используйте чекер как детектор слабых мест, а не как панацею.

Всем удачи и оферов🍀
👏7🔥1
prodigy 🔥 PROPERTY в ООП - РАЗБИРАЕМ НА ПАЛЬЦАХ! 🔥

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

Например у нас есть класс 👇 с защищенной переменной.

class Person:
def __init__(self, name, old):
self.__name = name
self.__old = old


И чтобы с ней работать вне этого класса, как вы помните, необходимо создать доп. методы в классе. Например:

    def get_old(self):
return self.__old

def set_old(self, old):
self.__old = old


property - упрощает создание сеттеров и геттеров(чтобы не писать/запоминать 100500 различных методов)

Один из вариантов создания такой:

 old = property(get_old, set_old) . 


Где get_old, set_old - соотествтенно гетер и сетер.

Как видим из синтаксиса - это декоратор, можно записать как выше, но лучше и практичней делать вот так вот:

class Person:
def __init__(self, name, old):
self.__name = name
self.__old = old

@property
def old(self):
return self.__old

@old.setter
def old(self, old):
self.__old = old

@old.deleter
def old(self):
del self.__old


То, что мы сделали, эквивалентно предыдущему варианту с тем лишь отличием, что теперь напрямую вызывать сеттер или геттер для локального свойства __old не получится. У нас остался один интерфейс взаимодействия – объект-свойство old. Именно так чаще всего делают на практике.

Так же есть еще один интересный момент в этом👇 Но не буду захламлять этим голову) Особо познавательным - скрытый текст в самом низу.

Ставьте реакции, спрашивайте в комментах, чтобы понять нравится, интересно, полезно или же нет😑:
знал это → 😎
узнал новое → 🤔
полезно → ❤️
есть вопросы → пишите

Та самая муть - можно не читать:
p = Person('ВАся', 25)
p.old = 35
p.__dict__['old'] = 45
print(p.__dict__)
print(p.old) # - что тут выведется, как думаете? кто знает?)

Например, можем создавать локальное свойство old в экземпляре класса, но при выводе и взаимодействии с ним будет использоваться то, что в защищенной переменной. Хотя, казалось бы, по логике должно же меняться локальное свойство old.
И ТАКОЕ СВОЙСВТВО БЕРЕТСЯ ВПЕРЕД( В ПРИОРИТЕТЕ НАД ДАЖЕ НАД СВОЙСТВОМ ЭКЗЕМПЛЯРА КЛАССА)
2🤔2
Вот как оказывается выглядит утро, когда встаёшь не в 12+, а вместе с рассветом🙀
👏6😍41
🤯 ДЕСКРИПТОРЫ: КАК Я ИЗБЕЖАЛ КОПИПАСТЫ В 3 СТРОКИ

Потратил 2.5 часа на 20-минутную тему из видео, но выжимку даю за 3 минуты чтения. Сколько раз пересматривал и пытался понять? - ДА

О чем тут вообще речь:
Мы создаем еще один другой класс, чтобы в нашем исходном классе его использовать и писать меньше одинакового кода в нем, но при этом чтобы он работал так же как и раньше. Лучше это или нет - судить вам. Речь про гетеры и сетеры (+"делеторы😁) Я бы сказал, просто вынос логики в другой класс. Так ли?🤔 А это даже наследование не проходилось еще🫠🫠🫠 Если не понятно о чем я - смотрите пример:

Задача: Класс для 3D точек в пространстве. Создать в нем приватные координаты и методы чтобы с ними можно было взаимодействовать.

БЫЛО (20+ строк кода):
class Point3D:
def __init__(self, x, y, z):
self._x = x
self._y = y
self._z = z

@staticmethod
def verify_coord(coord):
if type(coord) != int:
raise TypeError('Координата должна быть целым числом')

@property
def x(self):
return self._x

@x.setter
def x(self, coord):
self.verify_coord(coord)
self._x = coord

# и так еще 2 раза для y, z... а если их больше будет?!


⚡️ СТАЛО (магия дескрипторов):

class Integer:
@staticmethod
def verify_coord(coord):
if type(coord) != int:
raise TypeError('Координата должна быть целым числом')

def __set_name__(self, owner, name): # а это что еще за зверь?!
self.name = '_' + name
# еще один вариант установки имени, как в property, аналог
# self.__name = f'_{owner.__name__}__{name}'

def __get__(self, instance, owner): # геттер
return getattr(instance, self.name)
# return instance.__dict__[self.name] # другой способ для примера

def __set__(self, instance, value): # сеттер
self.verify_coord(value)
setattr(instance, self.name, value)
# instance.__dict__[self.name] = value # другой способ для примера


Теперь класс Point3D выглядит таким образом, гораздо лучше ж?

class Point3D:
x = Integer()
y = Integer()
z = Integer()

def __init__(self, x, y ,z):
self.x = x
self.y = y
self.z = z


💡 СУТЬ ПРОСТЫМИ СЛОВАМИ:
Дескрипторы = "фабрики property". Один раз написал логику - используй для любого количества атрибутов!

🎯 КОГДА ПРИМЕНЯТЬ:
•Больше 2 property с одинаковой логикой
• Хочешь сделать код чище
• Устал от копипасты

🤔 СПОЙЛЕР ДЛЯ ЛЮБОЗНАТЕЛЬНЫХ:
А знаете, что дескрипторы бывают двух типов?

Non-data vs Data дескрипторы...

Как думаете, в чем между ними разница?
И какой тип мы использовали в примере выше? 🤔

💬 Пишите ваши версии в комментах!

А вы сталкивались с дескрипторами в работе?
Или предпочитаете "старый добрый" copy-paste?
Делитесь опытом - интересно, кому это реально пригодилось!

P.S. Если тема зашла - лайкните, допишу пару моментов с тонкостями! Или не допишу, как хотите😈
3🔥3
Держите немного буржуйской мотивации с ютуба🙃

P.S.
Буржуи были в моём понимании - это те, кто говорят на английскийском языке, не более того) не знаю откуда это так запомнилось, но смысл этого слова лишь в этом🙃
👍5
👁👁Тема на картинке, впечатления ниже. На этом всё.👁👁

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

Да сколько этих вообще магических методов есть? Ладно то их количество, но что потом пригодится для использования на практике? Что надо запоминать лучше, а про какие можно знать что существуют и потом к ним вернуться? В голове сейчас только одно - АААААААААААААА.

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

Но с другой стороны, вначале можно посмотреть как это делается, чтобы потом много раз использовать повторно. А вы как считаете?! Кто на какой стороне медали стоит?)
4
☎️📞🤙 Call me maybe ☎️📞🤙

Классы в Python можно вызывать как функции. Да, те самые обычные две скобки () при создании экземпляра.

В этот момент вызывается "магический метод" `__call__` 🧙‍♂️. По умолчанию он вызывает ошибку TypeError, если применяется к экземпляру класса без реализации.

Классы, которые так себя ведут, называют "функторы" 🧠. Странное название, ну да ладно 😁.

Но зачем это надо? 🤔 Давайте разберемся на примерах.

1) Простой счетчик
class Counter:
def __init__(self):
self.__counter = 0

def __call__(self, *args, **kwargs):
print('__call__')
self.__counter += 1
return self.__counter


c = Counter()
c()
c()
res = c()
print(res) # 3 🎯


2) Счетчик с параметром:
Можем немножко изменить код, чтобы туда можно было передавать аргументы, Что выведется в последней строчке тогда, как думаете?
class Counter:
def __init__(self):
self.__counter = 0

def __call__(self, step=1, *args, **kwargs):
print('__call__')
self.__counter += step
return self.__counter


c = Counter()
c2 = Counter()
c()
c(10)
res = c(3)
res2 = c2(-5)
print(res, res2) # что выведет? 🧠


Еще пару вариантов:

3) Замена замыканий функций:
+ в чат если помните что это такое 🙃. Пример для обработки строки через strip(). Но можно придумать что угодно другое.
class StripChars:
def __init__(self, chars):
# символы для удаления в конце и начале строки
self.__chars = chars

def __call__(self, *args, **kwargs):
if not isinstance(args[0], str):
raise ValueError("Аргумент должен быть строкой")

return args[0].strip(self.__chars)

s1 = StripChars("?:!.; ")
res = s1("; Hello World! ")
print(res) # "Hello World"

4) Реализация декораторов, с помощью классов.
Математика вошла в чат 📊. Здесь вычисляется значение производной функции в конкретной точке х.
import math

class Derivate:
def __init__(self, func):
self.__fn = func

def __call__(self, x, dx=0.0001, *args, **kwargs):
return (self.__fn(x + dx) - self.__fn(x)) / dx

@Derivate
def df_sin(x):
return math.sin(x)

# df_sin = Derivate(df_sin) # в "лоб"
print(df_sin(math.pi/3)) # производная синуса 🧮


Итог: Функторы — это мощный инструмент, когда нужно сохранять состояние между вызовами или создавать умные декораторы! 🚀

А вы используете функторы в своих проектах? Делитесь в комментариях! 👇

P.S. Кто угадал результат во втором примере? 😄
🤯2🔥1
Всем доброе утро!☺️

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

Встал в 2 ночи и всё...не могу заснуть. Ну думаю что делать? пойду дорешаю несколько задачек по простой теме(позже пост). А среди них..опять прокрался злосчастный двусвязный список и нагородили новых методов еще.😬

Коротко о задаче:
Верно решили 3 114 учащихся
Из всех попыток 22% верных


Наверно 2.5+ часа решал.🫠🫠🫠

Часа полтора логика где-то + написание. Пошел ее проверил по своим тестам. Всё ок

И еще где-то час ушло на то, что я решил "сэкономить" время, пропивав data-decriptor вместо трёх одинаковых property . Ну а че? Думал так красивее, быстрее и правильнее. Ага...🤡

Какого же было моё удивление, когда assert-ы в итоговой проверке не проходят. Хотя казалось бы...все случаи предусмотрел.

И в чем проблема была, как думаете???😢
    def __set_name__(self, owner, name): # а это что еще за зверь?!
self.name = '__' + name # 1 способ - не подошел (хотя так показывали в теории)
self.name = f'_{owner.__name__}__{name}' # 2 cпособ(верный в моем случае)


Т.е....

В первом способе вручную создавалась имя атрибута, которое начиналось с двух подчеркиваний, например, __next.

➡️ Имя атрибута в словаре объекта: __next ⛔️
➡️ Что ожидали ассерты: _ObjList__next

Почему не работало: Ассерты искали атрибут с именем _ObjList__next, но дескриптор создал атрибут с именем __next. Python считает эти два имени абсолютно разными. Выходит обращался не по тому "адресу".

И вот из-за такой, казалось бы мелочи, тратится много времени и нервов на решение задач. Про уставшие глаза, желание забросить всё и сейчас я вообще молчу🧠Ну ничего движемся дальше.

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

Вопрос к вам:
А какие у вас сейчас темы сложно даются? Интересно узнать, делитесь, не стеснятесь😼
😱2
Прощаемся с <object at 0x...> раз и навсегда! 👋

Надоело видеть в консоли нечитабельную ерунду вроде <__main__.Cat object at 0x000002359011C160>? 🤔
Давайте сделаем вывод объектов Python понятным и информативным для человека!

В этом нам помогут магические методы __str__ и __repr__. Они "отрабатывают" в момент отображения объекта и превращают технический мусор в красивую строку. В чем разница между ними?

1️⃣ __str__ — для пользователей (когда вы делаете print() или str()).
2️⃣ __repr__ — для разрабов (в режиме отладки или консоли).

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

Пример с котиками😼
class Cat:
def __init__(self, name):
self.name = name

def __repr__(self):
return f'{self.__class__}: {self.name}'

def __str__(self):
return f'Имя кошки: {self.name}'


cat = Cat('Василий')
cat # в консоле выведет: <class '__main__.Cat'>: Василий
print(cat) # Имя кошки: Василий
str(cat) # Имя кошки: Василий

И еще два довольно простых метода __len__, __abs__.

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

class Point:
def __init__(self, *args):
self.__coords = args

def __len__(self):
return len(self.__coords)

def __abs__(self):
return list(map(abs, self.__coords))


p = Point(1, -2)
print(len(p)) # 2
print(abs(p)) # [1, 2]


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

Как вам такие "магические" методы? 👇
🔥 — Огонь, приму на вооружение!
🤔 — Знал, но освежил память.
🐱 — Котики — топ!
🔥52
Симуляция работы программиста 👨‍💻

Если есть тут те, кто реально работает, скажите, насколько я попал? 🤔

В общем, вчера проснулся в 4 утра. Дальше — все как в тумане, неожиданно наступило 8 часов 😶 Время ехать в офис. Но так как я «работаю» удаленно, до 9:30 еще валялся и досыпал. Кайф!

Дальше открываю Jira Stepik. Смотрю задачи, беру ту, что «горит». Пару дней назад кое-что отложил, вот пришлось срочно доделывать. Разобрался с этим и приступаю.

В итоге просидел до 17:30, не считая перерывов на кофе и что-то сделать покушать. Получился целый рабочий день. Не думал, что может так затянуть! Раньше вообще размышлял, как можно столько часов подряд сидеть и кодить? А нет, оказывается, можно))

Пошел четко по плану. К моему удивлению, задача, которая на первый взгляд казалась самой легкой, отняла больше всего времени (целых 2.5 часа!). А самая непонятная (по описанию) была не такой уж и трудной.

В общей сложности сделал 7 задач. Забудьте про те 25 в день, про которые писал раньше 😂 Важно, сколько времени ты уделяешь работе, а не количество. Просто прошлым способом проще заставить себя начать.

Как только прошло 8 рабочих часов, ни минуты не задерживаясь, закрыл всё к чертям! 😎 Теоретически мог бы заниматься дальше, но чувствую, продуктивность была бы уже около-нулевая.

А у вас как проходят рабочие будни? Делитесь в комментах! 👇🙃
Узнали себя? - Ставьте лайк😈
🔥5
Магические методы для арифметических операторов в Python 🔢

Знакомьтесь с основными магическими методами:
add() – сложение
sub() – вычитание
mul() – умножение
truediv() – обычное деление
floordiv() – целочисленное деление
mod() – остаток от деления

Лучше один раз увидеть, чем 100500 раз прочитать! 👀 Внимание - очень много букв😁😁😁

Возьмем класс для работы со временем. Время храним в секундах (макс. 86400 - секунд в сутках):
class Clock:
__DAY = 86400 # секунд в сутках

def __init__(self, seconds: int):
if not isinstance(seconds, int):
raise TypeError("Секунды должны быть целым числом")
self.seconds = seconds % self.__DAY

def get_time(self):
s = self.seconds % 60 # секунды
m = (self.seconds // 60) % 60 # минуты
h = (self.seconds // 3600) % 24 # часы
return f"{h:02}:{m:02}:{s:02}"

Добавляем сложение

Сначала научим складывать с числами:
    def __add__(self, other): # 
if not isinstance(other, int):
raise ArithmeticError("Правый операнд должен быть типом int")
return Clock(self.seconds + other)

Теперь работает:
с1 = Clock(1000) 
с1 = с1 + 100
print(с1.get_time()) # 00:18:20

Усложняем - складываем два объекта Clock:
    def __add__(self, other):
if not isinstance(other, (int, Clock)):
raise ArithmeticError("Правый операнд должен быть типом int или объектом Clock")

sc = other if isinstance(other, int) else other.seconds
return Clock(self.seconds + sc)

Теперь:
c1 = Clock(1000)
c2 = Clock(100)
c3 = c1 + c2
print(c3.get_time()) # # 00:18:20

Закончили? Неа!
Не работает: c1 = 100 + c1  # Ошибка!

Добавляем обратное сложение 🔄
    def __radd__(self, other):
return self + other # перекидывает в __add__(self, other) .

Теперь 100 + c1 работает. Почему кидает в add? Честно - я не до конца понял 😅
c1 = Clock(1000) 
c1 = 100 + c1
print(c1.get_time()) # 00:18:20

Но метод выше можно еще реализовывать например таким способом, тут всraddее:
    def __radd__(self, other):
return self.__add__(other)

Ну теперь уж точно всё, подумали вы. Нет😂😂 все еще не работает такой стиль c1 += c2🙈
Точнее работает, но не так. как хотелось бы. Мы пока что возвращаем(создаем) новый объект, а здесь новый эзкемпляр создавать не надо. Надо просто изменять на месте, для этого напишем так.

Изменяем объект на месте (не iadd новый)
    def __iadd__(self, other):
print("__iadd__")
if not isinstance(other, (int, Clock)):
raise ArithmeticError("Правый операнд должен быть типом int или объектом Clock")

sc = other if isinstance(other, int) else other.seconds
self.seconds += sc

return self # возвращаем тот же объект!

Теперь c1 += c2 изменяет сам c1 🎯

Важный нюанс:
🟡 + создает новый объект
🟡 += изменяет существующий

Для изменяемых классов (как списки) можно всегда возвращать старый объект.
Другие методы делаются абсолютно аналогично.

Итог:
Теперь вы знаете, как работают операции в int, float, str! Все ошибки, которые вы видели - это как раз проверки в этих dunder методах.

Как вам такие "магические" методы? 👇
🔥 — Огонь, приму на вооружение!
🤔 — Знал, но освежил память.
🐍 — Здесь притаился питон.raddто объясниaddму __radd__ вызывает __add__ в первом варианте реализации этого метода? Жду в комментах! 👇
🤔3🔥1
Сравнения в Python: как научить классы понимать ==, !=, >, <, >=, <= 🔍

Продолжаем разбирать магические методы! После арифметики из прошлого поста переходим к сравнениям:

eq
()
– для равенства ==
ne() – для неравенства !=
lt() – для оператора меньше <
le() – для оператора меньше или равно <=
gt() – для оператора больше >
ge() – для оператора больше или равно >=

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

Но их можно легко исправить.
    def __eq__(self, other):
if not isinstance(other, (int, Clock)):
raise TypeError('Оперант справа должен иметь тип int или Clock')

other_seconds = other if isinstance(other, int) else other.seconds
return self.seconds == other_seconds

Пример:
c1 = Clock(1000)
c2 = Clock(1000)
print(c1 == c2) # True


Другие методы можете сами догадаться как прописывать, аналогично этому __eq__

Занимательный факт: можно дополнительно не реализовывать метод для сравнения на неравенство - (ne) , если уже реализован (eq). Как думаете почему? А если реализовали метод "<", сработает ли ">"?🧐🧐🧐

Подсказка: Python пытается быть умным и использовать имеющиеся методы для обратных операций! 🔄
🔥3
"Вайбкодер" vs Программист: Новая эра или просто хайп?

Смотрю сейчас вакансии и натыкаюсь вот на такую. Название "Вайбкодер" - интересно))

И сразу мысль: может я не тем занимаюсь и зря всё это учу? Чисто взял, научился создавать промпты для нейронки — и ты уже в IT? Кажется, что это легкий вход, особенно когда видишь "опыт не требуется" и "удаленка".

Но за этим хайповым названием скрываются вполне реальные технические требования: знание Python, работа с API, автоматизация, n8n, VS Code, OpenAI и Claude. Это не просто "поболтать с чат-ботом".

Всем, кому интересно полное описание - вот ссылка на вакансию.

Мое мнение - нет, это не замена классическому кодингу(хотя я задумался😅). Просто новая ниша. Учиться все равно нужно много. А вы как считаете?
🤔5