Интересная Python задачка с собеседования - решаем, усложняем и снова решаем!
Разбираем задачку на Python с собеседования, усложняем её несколько раз и решаем снова. Смотреть до конца, рассматриваются разные возможности языка:)
Мой курс «Хардкорная веб-разработка» - course.to.digital
Книжный клуб Ботаним!, где мы читаем хорошие ИТ-книги: botanim.to.digital/
Telegram: t0digital.t.me
0:00 Задача с собеседования
1:13 Решаем!
6:13 Усложняем задачу
8:00 Еще усложняем
14:27 И ещё усложняем
18:28 Финальный вариант
/****************** about ******************/
Меня зовут Алексей Голобурдин, я программирую с 2004 года и на этом канале делюсь своим опытом. Я основатель и руководитель компаний:
- Диджитализируй digitalize.team, разрабатываем сложные IT системы для бизнеса;
- Salesbeat salesbeat.pro, комплексный модуль доставки для интернет магазинов.
Telegram канал - t.me/t0digital
ВК - digitalize.team
RuTube - rutube.ru/channel/24802975/ab...
Дзен - dzen.ru/id/6235d32cb64df01e6e...
Пікірлер: 435
Мой курс «Хардкорная веб-разработка» - course.to.digital Вжух!
Блин за первые 6 минут я понял как реализуются декораторы, с которыми у меня были проблемы, затем я понял как для одной из задач через словарь можно было вызывать функцию, а на последок еще лучше стал понимать как готовить классы)) Спасибо огромное за разбор!)
@t0digital
2 жыл бұрын
Отлично, рад, что полезно!
@PrefixKrema
Жыл бұрын
>затем я понял как для одной из задач через словарь можно было вызывать функцию, Ты только что паттерн стратегия.
У тебя очень крутая подача, с интересном смотрю каждое твое новое видео, не останавливайся ты делаешь этот мир лучше)))Спасибо))Побольше видяшек с таким подробными боевыми задачками)))Обнял))
Топово) Хотелось бы побольше таких видео, с лайв кодингом, рефакторингом и т.д., очень интересно) Спасибо!
Спасибо, всегда с удовольствием смотрю твои ролики.
Спасибо, прекрасное видео. С финального варианта нужно было и начинать) Проверил в pyCharm, все прекрасно работает, да и еще подсказки облегчают понимание логики кода. Жду новые видео с вундервафлями в мире пайтона для повседневных задач.
Классно получилось, делай такое по чаще ))
Отличная подача, бодрая, нескучная, все понятно, не знаю, как новичкам, но мне с 5 годами в java все абсолютно было понятно
Просто наслаждение для мозга. Умница, спасибо!
Давно программирую, но до конца сам не допер) Спасибо за видео. Всех благ вам!
@t0digital
2 жыл бұрын
Спасибо!
Было очень интересно. Спасибо!
Фига се!!! Очень круто! Один минус, на работе не удивлю завтра ни кого, так как почти все смотрят этот канал )))))
Дядька, ты крут !!! Спасибо :))
Великолепный видос. Спасибо!
Блин это очень круто, спасибо!
Очень понятное и полезное видео получилось! Спасибо тебе большое. Подача материала на высоком уровне. Вот бы еще научиться так виртуозно пользоваться VIMом...
Крышесносно! Спасибо!
спасибо большое, очень круто!
@t0digital
2 жыл бұрын
Рад, что полезно!
И вновь вкусняшка! Python и ООП - сила! Благодарю!
Круто, спасибо 🙏
Ничёсе поворотти, спасибо большое ^^
Спасибо большое! Спойлеры: в 3-ем варианте продолжил перебирать синтаксис и использовал while. С атрибутами для функций - отлично, не знал, что так можно, очень удобно. Со словарём - прикольно, в качестве тренировки: не сразу въехал, пропустил вызов на возврате из wrapper, но после двухчасового перерыва уже легко и осознанно пересобрал сам. Про классы - мелькнула мысль ещё в начале видео, но после трёх примеров с функциями переключился и вообще перестал рассматривать их как опцию. Первый вариант сначала не понял при чём там конвертация в строку - у меня вместо принтов стояли ассерты с интами. А о последнем тупо не знал, что так можно - и вот это прямо офигенно, очень в работе этого не хватало. В целом, казалось бы, всего несколько простых задачек, с виду вовсе не про ООП, а как-то сразу стало понятнее, как в принципе работают объекты и как их можно использовать.
Алексей просьба сделать видос про DevContainers в VSCode если это возможно конечно же. Ваш контент топ , я кайфую при просмотре
Спасибо. Познавательно.
Интересные решения, но еще можно решить через while, пример: result = 0 def chain_sum0(num=None): global result while num is not None: result += num return chain_sum0 return result К решению пришел сам, сразу после ограничения по if.
@MrTaramka
Жыл бұрын
да, странно что while не был упомянут, это классическая замена if
Офигенно!!! Очень интересно, масштабно и при этом легко и увлекательно!
Оч классный видос. До конца конечно надо дебаггером будет пройти чтобы понять как оно работает. По больше бы таких видосов. Спасибо))
@eduardmart1237
2 жыл бұрын
А какой лучший деббагер для питона?
@IgnatikVodichka
2 жыл бұрын
@@eduardmart1237 мне очень нравится дебажить через Thonny. Визуально классно показывает как он заходит прям в код и выполняет его по кускам.
Спасибо) отличный видос
@t0digital
2 жыл бұрын
Спасибо!
Реально спасибо!
видео понравилось! на примере показали, что в питоне не нужно думать функциональными ЯП, а лучше, компактнее и быстрее использовать классы
@AwakenDrow
Жыл бұрын
Только не классы, а объекты)
ТЗ: повысить градус идиотизма 🤣
Очень крутая подача
Для варианта с функцией и без ифов, траев и диктов можно так: def chain_sum(number=0): numbers = [number] def wrapper(*args): return (args and (numbers.append(args[0]) or wrapper)) or sum(numbers) return wrapper
@user-vh4vg2pb2p
2 жыл бұрын
Я на этом этапе похожее очень решение придумал: тоже с and/or логикой, только остальное так же ,как у Лёши. def chain_sum(number): result = number def wrapper(number2=None): nonlocal result result += number2 or 0 return number2 and wrapper or result return wrapper
@andreymelnikov8428
2 жыл бұрын
@@user-vh4vg2pb2p Если number2 равен нулю, вернется result. number2 or 0 работает, конечно, но лучше так тоже не делать, т.к. у нас должно быть две логические ветки number2 is None и number2 is not None. Например (так, конечно, тоже делать не нужно, но логика выдерживается): return (number2 is None and result) or ((result := result + number2) is not None and wrapper)
@user-yt8pz8ig3l
2 ай бұрын
забыли while который по факту является таким себе if блоком а с диктами удивил оверинжиниринг автора мое решение def chain_sum(number): total = number def wrapper(number=None): nonlocal total total += number or 0 return {None: total}.get(number, wrapper) return wrapper
Vim, python, изящные решения все как мы любим спасибо:)
У меня взорвался мозг от третьего варианта 😅 спасибо за увлекательное видео!!
Отец , твои видосы остануться для нас навсегда. bless you
@t0digital
2 жыл бұрын
Спасибооо 💪
Всю эту задачу можно было сделать ещё через операторы: код на пастбине с идентификатором uuM9YaXL. Там же через isinstance можно узнать это инт или нет и через and если это int продолжить цепочку операторов не используя инт, например return isinstance(number, int) and number. Но задачка топовая! Ролик очень интересный! Спасибо за контент!
Не думал что можно наследоватся от обьекта int , потрясающе )
@FilSerge
2 жыл бұрын
Int это класс
Додумался только до наследования от инта) остальное вообще не знал и представления не имел) спасибо за урок, очень полезный
@t0digital
10 ай бұрын
Спасибо, рад, что полезно!
Вместо написания inner() можно было использовать chain_sum(wrapper.result + number2)
Каждый раз как смотрю как ты работаешь в неовим и как у тебя это выглядит хочется попробовать. А потом что-то сдерживает. Кажется много усилий надо чтобы перейти на него с pycharm или vs code и выйти на тот же уровень привычки и скорости.
Достаточно интересно
Супер!
Спасибо за видео. Вы задумывались над форматом: публичные собеседование? Что-то подобное делает Андрей Пронин. Мне кажется, было бы очень интересно.
@t0digital
2 жыл бұрын
такое делать не хочу, неинтересно
это ОЧЕНЬ круто
Господи, это гениально, я в шоке
Это было круто!
@t0digital
2 жыл бұрын
Спасибооо!
Красивое!
Лаконичное решение с наследованием от int. Даёшь больше сферических коней в вакууме! 😄
@mndtr0
2 жыл бұрын
Красивый у вас однако калькулятор в видео на канале!
@shtoshpython
2 жыл бұрын
@Главный Редактор хех, благодарю. Выглядит как проплаченный комментарий :)
@t0digital
2 жыл бұрын
@@shtoshpython и правда симпатичный:)!
@shtoshpython
2 жыл бұрын
@@t0digital Благодарю, Алексей, от вас приятно услышать. (Я заплатил им обоим)
@nseed8894
2 жыл бұрын
@@shtoshpython Классный калькулятор👍(мне не платили)
Классы как всегда рулят )))
Спасибо за все видео. В функции без if можно с помощью while loop def chain_sum(num1): def wrapper(num2=None): while num2: wrapper.result += num2 return wrapper return wrapper.result wrapper.result = num1 return wrapper а в классах не наследуя от int можно сделать имплементацию __int__ method и пропустить наш объект через int() def __int__(self): return self._num print(1 + int(chain_sum(5))) import math print(math.sin(int(chain_sum(100)))) также можно делать имплементацию всех операторов, но каждый по отдельности def __radd__(self, other): return self._num + other def __add__(self, other): return self._num + other
Решение в одну строчку это домашние задание? Шутка, очень круто! Спасибо!!!
гениально!
Чертов __call__. Даже super легче в голове уложить. Спасибо, интересно
19:05 __add__, __mul__, __floordiv, __div__, __mod__, __pow__ и др. необходимые, но проще и лучше вышло с наследованием int
@ivernik
2 жыл бұрын
С этими методами вы бы просто переизобрели велосипед.
@blackcatdevel0per
2 жыл бұрын
@@ivernik Но как одно из решений сойдёт
@iliadubrovskii8204
2 жыл бұрын
@@blackcatdevel0per скорее всего это не будет полноценным решением и после такого будут еще вопросы, чтобы точнее описать поведение int-а, в конце концов ты должен будешь прийти к наследованию от int)
@izaslavs
2 жыл бұрын
Безусловно технически возможно, но очень не элегантно.
Если принять концепцию, что вызов объекта может менять сам объект, то в реализации __call__ можно не создавать новый объект, а добавлять к self._number и возвращать self. Экономия памяти)))
@VGCor
Жыл бұрын
Код в студию пожалуйста :)
@Dmi3S
Жыл бұрын
@@VGCor In [1]: class chain_sum(int): ...: def __call__(self, number=0): ...: self += number ...: return self ...: In [2]: chain_sum(5)(2) Out[2]: 7
@Dmi3S
Жыл бұрын
Ну и если говорить об экономии памяти, то в класс добавить __slots__ = []. 104 байта экономии.
Прикольно получилось. Я не смог такой ход с классами придумать. Благодаря этому видео, я как-то даже приисполнился мудрости... ;) Кстати, не уверен, что во всех вариантах кроме последнего (где всё работает Ок) можно вызвать первую chain_sum() без аргумента, типа: chain_sum()(5)(6) Хотя конечно это легко исправляется определением по умолчанию number=0 Идея в том, что при создании функции в которую кто-то будет совать какие-то значения, важно корректно обрабатывать различные вырианты. Ну, к слову, без if в Python3.10 можно было ещё использовать match
@bokshalex
Жыл бұрын
Ну match это то же самое) Думаю его тоже бы не приняли
Гений!
Без ифов так ещё можно from functools import partial def chain_sum(x=None, result=0): return (x is None and result) or partial(chain_sum, result=result + x)
На 5:56 ты говоришь, что возникает рекурсия, но разве она здесь есть? Функция просто возвращает ссылку на саму себя, а не вызывает себя, по сути когда мы пишем сhain_sum(5)(100)(-10)...() конекст выполнения wrapper'a в стеке не сохраняется после каждого вызова так как функция полностью завершается и возвращает результат (число или ссылку на саму функцию), и мы можем вызывать эту конструкцию действительно неограниченное количество раз. Можно это даже проверить, написав что-то типа sum = chain_sum(1) for _ in range(1, 2000): sum = sum(1) print(sum()) Всё спокойно работает и 2000, и любое другое число раз, переполнения стека не происходит
@trapwalker
Жыл бұрын
верно. нет там никакой рекурсии. автор ролика просто ошибся. бывает.
def chain_sem(a=None): return lambda x=None: chain_sem(a + x) if x else a можно ещё так. спасибо за интересную задачу)))
@2daemn
Жыл бұрын
chain_sem(10)(5)(0)() Будет неправильно считать. Ваш вариант отличный, но делайте if x is not None
Оч круто!!!
@t0digital
Жыл бұрын
Спасибо!
Класс!👍
Интересная задачка. Последний случай не понравился тем что будет некорректно работать с флотами. Дополнил решение. Теперь вот такое может работать print(1 + chain_sum(3.21)(3)(1)(0.221)) from typing import Generic, TypeVar T = TypeVar("T", int, float) class chain_sum_int(int): def __call__(self, addiotion = 0): return chain_sum(self + addiotion) class chain_sum_float(float): def __call__(self, addiotion = 0): return chain_sum(self + addiotion) class chain_sum(object): type_dict = { int : chain_sum_int, float : chain_sum_float } def __new__(cls, num : Generic[T]): return cls.type_dict[type(num)](num)
последний вариант, кажеться, еще через дандер метод add можно реализовать, но ваш вариант явно красивее
@Nabokka
2 жыл бұрын
Помимо add нужно будет реализовать sub, mul, div. И при этом ты оставляешь огромное поле для собеседующего для подкопв
Алексей, а вы не думали сделать точечные курсы на конкретные темы? (Асинхронность, вебсокеты, например)
@t0digital
2 жыл бұрын
Думаете, это хорошая идея? Я думал об этом
@FilSerge
2 жыл бұрын
@@t0digital Однозначно хорошая, с вашей-то подачей, опытом и знаниями!
Первое же решение, которое пришло в голову: class ChainSum(int): def __init__(self, number=0): self.current_state = number def ChainSum(self,number): return ChainSum(self.current_state + number) def __str__(self): return f"{self.current_state}" def main(): b = ChainSum(5) print(b) c = ChainSum(5).ChainSum(2) print(c) d = ChainSum(5).ChainSum(100).ChainSum(-10) print(d) if __name__ == "__main__": main() задачу выполняет, но синтаксис не тот. Рад что был не далек от правильного решения и узнал про __call__
Спасибо за видео, помогло осознать, что не надо лезть в программирование и все заявления про "простоту" питона - замануха для дурачков с целью продажи "курсов". Весьма отрезвляюще, лучше становиться вором или проституткой /s__off
@sovunia
2 жыл бұрын
питон и вправду лёгкий язык
@zluka7951
2 жыл бұрын
питон по прежнему простой, сложная сама задача (хотя скорее своеобразная)
@4iterillo
2 жыл бұрын
А никто не говорит, что питон простой. У него низкий порог входа, т.к. простой синтаксис, нет работы с памятью и много готовых библиотек. Для питона надо не так много времени, чтобы уже можно было начинать хоть что-то полноценное писать самому и пробоваться на позиции джуна. Но вот чтобы стать дейс-но хорошим спецом потребуется немало времени и опыта, это да...
спасибо
как круто ааааа
До последнего варианта я так и не додумался, хотя он самый простой. Забавно.
@Nabokka
2 жыл бұрын
Он прост в написании, но за ним достаточно глубокие знания Питона
@dann1kid
2 жыл бұрын
@@Nabokka так и происходит. Узнаешь новое - идешь переписывывать на более простое и изящное
Но если серьезно, у меня вопрос: в свифте можно это реализовать еще через передачу вариадического (variadic) параметра в функцию.Есть ли такое в питоне?
Спасибо.
На кодварсе такую видел, 5кю вроде была :)
Го обзор на первую бета-версию питона 3.11, там много всего интересного)
В случае с callable-классом можно не переопределять __str__ и сделать короче, не создавая новые инстансы класса, а сохраняя все в одном: class chain_sum(object): def __init__(self, number): self.sum = number def __call__(self, value: int = 0): self.sum += value return self.sum if value == 0 else self print(chain_sum(5)()) # 5 print(chain_sum(5)(2)()) # 7 print(chain_sum(5)(100)(-10)()) # 95 Запись chain_sum(5) обращается к __init__ методу и возвращает сам инстанс, а вот последующие (100)(-10)() используют этот инстанс но уже вызывают метод __call__, поправьте если я не прав, но вариант с наследованием от int конечно гораздо элегантнее
Еще вариант - решить эту задачу без рекурсии. Я сделал, но каждый тип операции с цифрами надо прописывать отдельно в магических методах.
гениально
У меня есть несколько замечаний по видео Первое замечание то что не очень понятно почему chain_sum() не равно 0, хотя по логике я бы ожидал 0 (это легко исправить) Второй момент это уже координальная проблема в решении, то что сохраняется только одно числа То есть код, выведет ошибку cs = chain_sum(10) assert cs(5)() == 15 assert cs() == 10 # тут будет ошибка, хотя я бы ожидал от функции то что ошибки не будет Третий момент, если запрещен if то лучше использовать кортеж и индекс брать по ----arg is None--- (то есть True это первый индекс, False это нулевой индекс, так будет меньше памяти тратиться) (Все замечания не подходят к классу последнему, но у последнего класса мне казалось что chain_sum()() должен выдавать ошибку, что-то типа число нельзя вызывать, а там будет 0, но может быть я тут ошибаюсь) Я бы предложил такое решение: import functools def chain_sum(arg=None, _i=0): return _i if arg is None else functools.partial(chain_sum, _i=_i + arg) А так спасибо большое за видео, задачка прикольная
@SklerozRu
Жыл бұрын
Я похожий вариант придумал, до просмотра решения автора ролика :) def chain_sum(num=None, *, prev=0): return prev if num is None else partial(chain_sum, prev=num + prev)
Агонь!
у меня есть задача, которую я решал на степике "долгое-лично-для-меня-время" ахахахха да-да, она прям жесть как похуже) могу скинуть если нужно
Как увидел задачу решил реализовать ее сам не смотря на решение и вот что получилось: answer = 0 def recursion_sum(*args): global answer if args: answer += int(*args) return recursion_sum else: return answer print(recursion_sum(2)(1)(3)()) мне кажется такой вариант выглядит проще, только переменная глобальная т.к при рекурсии ответ бы каждый раз переопределялся. Если кто знает как это решить, буду рад услышать. Так же момент с int(*args) - небольшой костыль, но так как я уверен что при вызове будет передаваться не больше одного аргумента, то можно и пренебречь. Хотя если надо, можно было бы переписать как: sum(map(int, args)) Вот как-то так, задачка интересная))
Интересно, а какие будут различия по времени выполнения каждого варианта кода?
КРУТО)))
Алексей, у меня к Вам такой вопрос: как вы используете докер на проектах? Оборачиваете в контейнеры сразу же и начинаете разрабатывать приложение уже вместе с докером, или оборачиваете уже под конец разработки, когда есть какая-то рабочая версия для продакшена? И какой подход всё-таки лучше если на проекте используется докер? Начинают проект и решил использовать докер, хотелось бы узнать Ваше мнение по использованию.
@t0digital
2 жыл бұрын
Те кто использует докер обычно сразу оборачивает, так удобнее. Мы не везде используем докер
@sogorich
2 жыл бұрын
@@t0digital Благодарю за ответ.
в класс можно было добавить методы по типу: __add__ и было бы намного лучше как мне кажется либо сразу уже наследоваться от int
Сеанс черной магии с последующим разоблачением! ))
Вот реально программист не тот, кто всё знает, а тот, кто умеет применить)) Знал все эти фокусы но решить не смог(
@t0digital
Жыл бұрын
Больше опыта и все сложится:)
Добрый вечер, не подскажите как называется шрифт который вы используйте в нвиме?
Здравствуйте. Вопрос не по теме видео, но очень важен для меня . Вы MacBook Air m1 уже пользуетесь + - год ,интенсивно его используете каждый день , хотел уточнить у вас , есть проблемы с потертостью окраса в местах где основном расположены кисть рук да и общем на вашем gold цвете?? Я стою перед выбором покупки m1 air , просто на авито не раз встречал фото цвета space grey где эти потертости окраса были очень видны и хозяева даже не особо им пользовались . Просто моем регионе есть в продаже только 2 цвета это gold и space grey , больше хотел silver но их нет в наличии
@t0digital
2 жыл бұрын
Привет! У меня золотой, использую активно, потёртостей вообще нет. По space gray стирается, да, не рекомендовал бы такой цвет
Я пробежался по вашему плейлисту по лайфхакам линукса , был восторге от увиденного, как вы пользуетесь линуксом знаете прекрасные методы максимального его использования для комфортной и продуктивной работы, просто прекрасная и очень понятная для обычного пользователя компьютера подача информации. И под одним из роликов вы закрепили комментарий с вопросом о том чтобы сделать большой курс по линуксу с Азов до профи . На что все отреогировали с восторгом . Но на канале я не нашел или не увидел этого курса по линукс . Я очень хочу освоить линукс и хотел спросить у вас этот курс сделан или в процессе ( когда будет готов)? Просто у вас отлично получается на простом языке объяснять порой сложный материал и ещё , что очень понравилось сразу наглядно все это показываете
@t0digital
2 жыл бұрын
Спасибо! Да, я планирую сделать такой материал по Linux, но пока не могу сориентировать по срокам выхода
@user-rp6bi5qj1n
2 жыл бұрын
@@t0digital Такой курс по линукс будет про мастхэв для людей которые решили изучить его , тем более с вашей подачей . Здоровья вам и вашим близким и успехов ваших делах и проектах . Ждём-с линукс 😁
Здравствуйте. Подскажите хороший курс по ООП на питоне
Жирный ЛАЙК
Класс ! Побольше бы подобных видео, хорошая подача По видео: я не видел как ты делал вызов новых функций в принте
Первая мысль была решить последним способом, но в задаче было слово "функция", поэтом посчитал что можно решить через функции)
Скажите пожалуйста для разработчика какой дистрибутив выбрать для освоения линукса Debian или Ubuntu?? Вы доисторических пор пользуетесь Debian- ом ?
@t0digital
2 жыл бұрын
Для сервера дебиан. Для десктопа у меня сейчас манжара
ДЯДЯ я улетаю от полученных знаний
интересно, можно ли такое сделать чисто рекурсией
Еще пару вариантов: 1. через match def chain_sum(sum): def helper(arg2=None): nonlocal sum match arg2: case None: return sum case _: sum += arg2 return helper return helper 2. через while def chain_sum(sum): def helper(arg2=None): nonlocal sum while arg2: sum += arg2 return helper return sum return helper
@esvesvesvesv
2 жыл бұрын
Или еще проще без врапперов и тд def chain_sum(arg=None): while arg: setattr(chain_sum, 'x', getattr(chain_sum, 'x', 0) + arg) return chain_sum return chain_sum.x (это до последнего усложнения, до него еще не досмотрел ))
@esvesvesvesv
2 жыл бұрын
Вот решение, которое работает и без скобок и со сколько угодно скобками ) (еще не смотрел какое решение будет в видосе, интересно!) class chain_sum: def __init__(self, arg): self.res = arg def __call__(self, arg=None): if arg: self.res += arg return self def __str__(self): return str(self.res)
сам часто для каких-то задач наследуюсь от str, dict и пр., но что int.self возвращает числовое значение, чёт не допёр )