Спасибо за урок много интересного подчёркиваю. По поводу "default" мне кажется в место него лучше "default.jpg" в static положить и сделать проверку в image.html {% load static %} {% if product.image %} <img src="{{ product.image.url }}" class="card-img-top" alt="{{ product.title }}"> {% else %} <img class="img-size" src="{% static 'img\default.webp' %}" alt="defaultCar"> {% endif %}
Очень подробно мне очень нравится, но в конце всё как-то усложнили нужно было просто добавить в style.css .card-flex { flex: 1 1 33% !important; } ну вообще спасибо большое смотрю учусь многому.
"Ой, добавился атрибут name..." Чтобы такого не случалось, есть дандер __slots__ . Пишется он в самом начале тела класса и приравнивается к списку либо кортежу, в котором перечислены в строчном формате все имена, которые будут использоваться внутри класса. В данном случае: __slots__ = ['__name', 'age'] Всё. Теперь при попытке присвоения нового атрибута увидите ошибку: "объект не имеет такого атрибута". И не сможет иметь. То же самое произойдёт и в случае, если дописать новый атрибут/метод в теле класса, но не добавить его имя в __slots__ .
"Если вы помните, в функции создаются локальные переменные, к ним нельзя обратиться..." Это к переменным. А к атрибутам и к методам функций очень даже можно. def homo(name=None, age=0): def inner(): inner.name = name inner.age = age def show(): return f'{inner.name} {inner.age}' show() inner.show = show inner() return inner a = homo() b = homo('Alex', 25) print(a.show()) print(b.show()) print(b.name) print(b) # как видите, это пространство имён функции Всё как доктор прописал, создаются самостоятельные объекты в виде копий пространства inner, у которых работают персональные атрибуты и методы. Замыкания и вообще процедурное программирование намного более мощная и гибкая штука, чем об этом обычно говорят.
Гораздо понятнее (и правильнее), во-первых, объяснить, что такое "пространства имён", что такое "область видимости" и что такое "инициация". А уже с эти багажом информации и эффект замыканий, и декорация, и поведение импортированных из левого модуля функций становятся просто очевидны.
"уникальных неупорядоченных значений". Здесь хорошо бы сделать сразу два отступления. Во-первых, рассказать, что такое функция hash. Зачем она -- уже другая история, факт в том, что и ключи словаря, и множество создаются с применением хэширования. Так вот, с точки зрения hash булевы переменные True/False и целые числа 1/0 -- одно и то же. При попытке собрать множество из этих четырёх значений внутри окажутся только два: hash всё превратит в числа. Эта же функция отвечает за то, что ни ключом словаря, ни элементом множества не может быть неизменяемый объект "кортеж", если он содержит хоть один изменяемый ээлемент -- например, список. Теперь насчёт порядка. Порядок во множестве есть. Но не зависящий от порядка ввода, а свой, согласно внутренним тараканам, точнее, согласно опять же результатам работы функции hash, она выдаёт "хэш-суммы" и вот они-то уже упорядочены. Поскольку хэш-сумма целого положительного числа равна самому этому числу -- очевидно, что если при создании множества используются только целые положительные числа, то множество окажется сортированным по возрастанию. А отрицательные целые числа пойдут следом после всех положительных и отсортируются в обратном порядке. Запустите этот код: import random s = set((random.randrange(- 1000, 1000) for x in range(100000))) # на входе каша из 100 тыс чисел от -1000 до 999 print(s) Фокус-покус!
Здесь (как и почти везде) из-за неверной трактовки чрезмерно сложное объяснение. Всё гораздо проще: and и or -- КОММУТАТОРЫ, они ничего не изменяют и не преобразовывают, они переключаются, возвращая один из двух "фрагментов кода" (это не обязательно просто значение, это и выражение и функция) в зависимости от того, чем в булевом смысле является содержимое ЛЕВОГО плеча оператора. and при получении в левое плечо "чего-либо", равнозначного False -- его и вернёт, при получении True -- переключится на то, что у него в правом плече. or работает ровно наоборот, переключится, получив в левом плече False. Никто никакие "True" не ищет. True and 1 => 1 1 and True => True False or 0 => 0 0 or False => False Всё это происходит не "сравнением", как сказано в ролике, двух результатов, а только оценкой той части выражения, что слева. Это важно понять, потому что иначе, будь в правом плече некое громоздкое вычисление (создание списка на сто миллионов, например), для "сравнения" оно бы запускалось каждый раз независимо от результата в левом плече, ведь надо же получить результат для "сравнения". Однако нет. Взять одно и то же выражение: lst1 = [0] * 10 lst2 = [1] * 10 for x in lst1: a = x or [*range(10000000)] print('OK') for x in lst2: a = x or [*range(10000000)] print('OK') Время выполнения этих двух циклов будет различаться на много порядков, В первом случае or будет каждый раз переключаться на создание списка, во втором -- просто прощёлкает цикл. Если заменить or на and, сработает наоборот. Вот и вся магия.
Здравстуйте! Можете ли вы по подробнее обьяснить о 15:45 то что получилось? Правильно ли я понял что вы сначала взяли всех женщин и с Union обьединили таблицы? Спасибо
Здравствуйте! Да. Все правильно вы поняли. Мы сделали первую выборку при помощи join. В результате получили всех женщин, а затем, просто сложили 2 таблицы. Здесь важно понять разницу между join и union. В первом случае таблицы связаны ключами, а во втором - нет. При сложении, вычитании и пересечении, главное - одинаковое количество колонок и не конфликтующие типы в них