Комментарии 13
Необычный подход изучения языка)
А можно такой же, скажем, для JavaScript на примере V8?
А можно такой же, скажем, для JavaScript на примере V8?
У каждого объекта всего один тип, который не меняется в течение жизни объекта (тип может поменяться в чрезвычайно редких обстоятельствах. Для этой задачи не существует API, и вы вряд ли читали бы эту статью, если бы работали с объектами с изменяющимися типами)
В большинстве же случаев можно ведь присваивать магическому атрибуту
__class__
новый тип, чем не API? Причем Питон проверяет совместимость memory layout объектов старого и нового типов (то есть такой трюк не сработает, например, для tuple или если один из типов имеет пользовательские слоты), и после смены типа объект действительно ведет себя по-новому.Или все-таки я чего-то недопонимаю, и даже в этом случае ob_type продолжает указывать на первоначальный тип?
P.S. Спасибо за интересные статьи, продолжайте в том же духе! :)
Сам спросил, сам отвечаю (./Objects/typeobject.c :: object_set_class):
Где
Все по-настоящему, успешное присваивание
...
3357 if (compatible_for_assignment(oldto, newto, "__class__")) {
3358 Py_INCREF(newto);
3359 Py_TYPE(self) = newto;
3360 Py_DECREF(oldto);
3361 return 0;
3362 }
...
Где
Py_TYPE
(./Include/object.h): 117 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Все по-настоящему, успешное присваивание
__class__
меняет тип объекта.И обрекает разработчика на казнь…
Да, документация не рекомендует так делать.
Like its identity, an object’s type is also unchangeable.
It is possible in some cases to change an object’s type, under certain controlled conditions. It generally isn’t a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly.Можете рассказать, что плохого может случиться? Когда можно, а когда не стоит менять тип объекта?
Или все-таки я чего-то недопонимаю, и даже в этом случае ob_type продолжает указывать на первоначальный тип?Насколько я понимаю, ob_type остается прежним. Был у меня на эту тему вопрос с самоответом.
В вашем случае вероятнее всего прокси переопределяет геттер для
Попробуйте в консоли:
__class__
, тип при этом действительно не меняется.Попробуйте в консоли:
>>> class A(object): pass
...
>>> class B(object): pass
...
>>> a = A()
>>> a.__class__ is type(a) is A
True
>>> a.__class__ = B
>>> a.__class__ is type(a) is B
True
Добрый день!
Планируются ли статьи, разбирающие встроенные типы данных Python и/или работу интерпретатора по оптимизации кода?
Спасибо.
Планируются ли статьи, разбирающие встроенные типы данных Python и/или работу интерпретатора по оптимизации кода?
Спасибо.
Я правильно понял, что диспетчеризация по предопределённым методам (
В общем, вопрос вызова методов объекта
__eq__
, __gt__
, __call__
и т.п.) не динамическая, а по всем остальным методам работает через хеш-таблицу?В общем, вопрос вызова методов объекта
foo.bar()
не затронут, а там должно быть интересно.Ответы в следующей части.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Python изнутри. Объекты. Голова