Развёрнутое пояснение: Выражение a + [3] порождает новый список, который затем присваивается переменной a, не затрагивая исходный объект, на который ссылается b. Если бы использовалось a += [3], вызвался бы метод __iadd__, изменяющий список на месте, и тогда b тоже бы изменился. Таким образом, оператор присваивания с + не модифицирует исходный список.
Подробное объяснение 1️⃣ Python 3 компилирует super() без аргументов в super(__class__, <first_arg>). 2️⃣ Компилятор создаёт __classcell__ — ячейку замыкания с классом B. 3️⃣ Внутри inner() Python ищет __class__ в замыканиях — находит B. 4️⃣ self берётся из параметра f(self) через цепочку замыканий. 5️⃣ super().f() → A.f(self) → возвращает "A".
Почему это важно
В Python 2 super(B, self) было обязательно. В Python 3 zero-argument super() работает через магию компилятора — даже во вложенных функциях.
1️⃣ case Animal() проверяет isinstance(d, Animal). 2️⃣ Dog — подкласс Animal, поэтому проверка возвращает True. 3️⃣ Выполняется print("A"), блок case Dog() пропускается. 4️⃣ Match не падает сквозь — только первый подходящий case. 5️⃣ print("done") выполняется в любом случае.
Почему это важно
Более общий паттерн сверху перехватывает частные. Чтобы Dog сработал — поменяйте порядок: Dog выше Animal.
Подробное объяснение 1️⃣ @dataclass создаёт __init__(self, tags=[]) — пустой список вычисляется один раз при определении класса. 2️⃣ u1 = User() и u2 = User() получают ссылку на один и тот же список. 3️⃣ u1.tags.append("admin") мутирует этот список. 4️⃣ u2.tags видит ту же мутацию — выводит ['admin']. 5️⃣ Правильно: tags: list = field(default_factory=list). Почему это важно
Тот же баг, что и в обычной функции, но скрыт за декоратором. default_factory создаёт новый объект для каждого экземпляра.