Атрибут __class__
всегда был ограничен в том, что является приемлемым, и классы Python могут быть намного более гибкими, чем типы, определенные в C.
Например, раздел __slots__
в документации по датамоделю гласит:
__class__
назначение работает, только если оба класса имеют одинаковые __slots__
.
и тот же документ вызывает атрибут instance.__class__
только для чтения :
Реализация добавляет несколько специальных атрибутов только для чтения к нескольким типам объектов, где они актуальны.
Таким образом, __class__
фактически не предназначался для записи, но это было в течение длительного времени и является очень полезным свойством.
Теперь, в вашем случае, назначение не разрешено, потому что целевые экземпляры относятся к типу, который не выделяет объекты в куче (область памяти процесса, которая увеличивается для размещения произвольного числа объектов, это где большинство Объекты Python расположены). Объекты, не размещенные в куче, обрабатываются по-разному (например, не подлежат подсчету ссылок), и если вы измените их тип, им внезапно придется управлять по-другому. Это в настоящее время не поддерживается.
Это было , кратко поддерживаемое в сборках-кандидатах выпуска Python 3.5, чтобы разрешить установку __class__
на модулях , но это вызвало обратный эффект, когда было обнаружено, что можно изменить тип интернированных неизменных значений:
class MyInt(int):
# lets make ints mutable!
(1).__class__ = MyInt
1
является внутренним значением , поэтому теперь все использование целого числа 1
везде в программе Python было изменено. Не то, что вам нужно, особенно если вы повторно используете память интерпретатора в нескольких процессах, как это делает Google App Engine! См. Issue # 24912 для ознакомления с информацией о низком уровне.
Но именно поэтому экземпляры модуля специально упоминаются в исключении, см. Настройка доступа к атрибуту модуля .
Вам придется найти другой путь для решения вашей проблемы. Например, возможно, ваша конкретная проблема может быть решена вместо этого с помощью обтекания экземпляров во что-то, что использует __getattr__
для передачи атрибутов обернутому экземпляру.