«Оператор with используется для обертывания выполнения блока методами, определенными менеджером контекста (см. раздел Менеджеры контекста оператора With)».
Оператор with / as запускает логику управления контекстом объекта, чтобы гарантировать выполнение действий при завершении безотносительно к любым исключениям в его вложенном блоке:
with open('lumberjack.txt', 'w') as file: file.write('Лиственница!') # Попытка обратиться к несуществующему атрибуту file.nonexistent_method() # AttributeError
Файл все равно будет создан, хоть программа и выпадет в исключение:
AttributeError: '_io.TextIOWrapper' object has no attribute 'nonexistent_method'
«При продумывании смысла имен в коде, основанном на классах, полезно помнить о том, что классы в точности как функции вводят локальные области видимости, а методы являются просто более вложенными функциями. В следующем примере функция generate возвращает экземпляр вложенного класса Spam. Внутри своего кода имя класса Spam присваивается в локальной области видимости функции generate и потому оно доступно любой вложенной функции, включая код в method; это соответствует букве Е в правиле LEGB:
def generate(): class Spam: # Spam - имя в локальной области видимости generate count = 1 def method(self): print(Spam.count) # Согласно правилу LEGB (E) доступно в области видимости generate return Spam()
generate().method()
... локальные области видимости всех операторов def объемлющих функций автоматически видны вложенным def».
«Но обратите внимание, что происходит, когда мы изменяем атрибут класса динамически за пределами оператора class: в итоге также изменяется атрибут в каждом объекте, унаследованном от класса. Кроме того, новые экземпляры, созданные из класса в течение текущего сеанса или запуска программы, также получают динамически установленное значение независимо от того, что указано в исходном коде класса.
...
Это полезная возможность или опасная ловушка? Судить вам. ... вы можете сделать работу за счет изменения атрибутов класса даже без создания одиночного экземпляра — методика, с помощью которой удастся эмулировать использование “записей” или “структур” в других языках. ...
class X: pass # Создать несколько пространств имен атрибутов class Y: pass
X.а = 1 # Использовать атрибуты классов как переменные X.b = 2 # Какие-либо экземпляры отсутствуют X.с = 3 Y.a = X.а + X.b + X.с
for X.i in range (Y.a): print(X.i)
Код выведет: 1 2 3 4 5
Здесь классы X и Y работают подобно модулям «без файлов» — пространствам имен для хранения переменных, которые не должны конфликтовать. Это вполне законный трюк в программировании на Python, но он менее уместен, когда применяется к классам, реализованным другими; вы не всегда можете быть уверены в том, что изменяемые атрибуты отдельного класса не являются критически важными для его внутреннего поведения».
TypeError: __init__() takes 2 positional arguments but 3 were given Ошибка типа: __init__() принимает 2 позиционных аргумента, но было предоставлено 3.
Проблема связана с тем, что вызов super в Chef не обращается к своему суперклассу Employee, но взамен делает обращение к родственному классу того же уровня и следующему в MRO, т.е. Server. Поскольку конструктор родственного класса имеет список аргументов, отличающийся от списка аргументов в конструкторе настоящего суперкласса, который ожидает только self и name, код перестает работать».
Изменение подмножества, например, обновление его значений, также приводит к обновлению df. Точное поведение сложно предсказать. Copy-on-Write решает проблему случайного изменения более одного объекта, явно запрещая это. При включённом CoW df не изменяется».
Режим copy_on_write означает "копирование при записи". Это оптимизация, которая позволяет pandas не создавать копии данных сразу при создании view или slice, а только тогда, когда данные действительно изменяются. Это значительно экономит память, особенно при работе с большими наборами данных и цепочками операций. Это дефолтное поведение для Pandas версии 3.0+.
Этот код исполнится, поскольку Serializer — это так называемый миксин (Mixin — англ. «примесь»). Самый доступное объяснение этой концепции можно посмотреть на этом англоязычном видео.
«В данном случае ветви дерева суперклассов разъединены (у них отсутствует явный общий предок), так что подклассы, которые их комбинируют, должны делать вызовы через каждый суперкласс по имени — распространенная ситуация с большинством существующего кода на Python, которую super не может решить напрямую без внесения изменений в код».
class В: def __init__(self): print("B.__init__")
class С: def __init__(self): print("C.__init__")
class D(В, С): pass
x = D() # По умолчанию выполняется только крайний слева