Pull to refresh

Comments 13

Необычный подход изучения языка)
А можно такой же, скажем, для 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 и/или работу интерпретатора по оптимизации кода?
Спасибо.
Я правильно понял, что диспетчеризация по предопределённым методам (__eq__, __gt__, __call__ и т.п.) не динамическая, а по всем остальным методам работает через хеш-таблицу?
В общем, вопрос вызова методов объекта foo.bar() не затронут, а там должно быть интересно.
Sign up to leave a comment.