When where and how can i change the __class__ attr of an object?

Я хотел бы иметь возможность сделать:

>>> class a(str):
...     pass
...
>>> b = a()
>>> b.__class__ = str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types

3 ответа

Решение

Я решил это следующим образом:

>>> class C(str):
...     def __getattribute__(self, name):
...         if name == '__class__':
...             return str
...         else:
...             return super(C, self).__getattribute__(name)
...         
>>> c = C()
>>> c.__class__
<type 'str'>

Python 2 не имеет единой иерархии объектов (т. Е. Не все происходит от класса объектов). Все, что является частью этой иерархии, может быть воспроизведено через __class__, но те, которые не могут быть изменены таким образом (или вообще, на самом деле). Они называются "типами" Python, и они жестко запрограммированы в C. Примеры типов: str, int, float, list, tupleи т. д. Это означает, что вы не можете использовать типы так же, как классы, например, вы не можете изменить класс экземпляра типа, вы не можете добавлять, удалять или модифицировать методы типов и т. д. Следующая транскрипция показывает разницу в поведении между типами, такими как str (жестко запрограммированные, нединамические конструкции C) и классы, которые я назвал A и B (изменяемые, динамические конструкции Python):

>>> str
<type 'str'>
>>> class A:
...     pass
... 
>>> a = A()
>>> A
<class __main__.A at 0xb747f2cc>
>>> a
<__main__.A instance at 0xb747e74c>
>>> type(a)
<type 'instance'>
>>> type(A)
<type 'classobj'>
>>> type(str)
<type 'type'>
>>> type(type(a))
<type 'type'>
>>> type(type(A))
<type 'type'>
>>> A.foo = lambda self,x: x
>>> a.foo(10)
10
>>> A().foo(5)
5
>>> str.foo = lambda self,x: x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'
>>> 'abc'.foo(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'foo'
>>> class B:
...     pass
... 
>>> a.__class__
<class __main__.A at 0xb747f2cc>
>>> a.__class__ = B
>>> a
<__main__.B instance at 0xb747e74c>
>>> 'abc'.__class__
<type 'str'>
>>> 'abc'.__class__ = B
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ must be set to new-style class, not 'classobj' object
>>> class B(object):
...     pass
... 
>>> 'abc'.__class__ = B
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types

Только классы, которые были определены с class Ключевое слово может быть использовано для __class__ назначение атрибута:

>>> class C:
    pass

>>> class D:
    pass

>>> C().__class__ = D
>>>

Я попробовал так!

>>> class C(str):
...     __class__ = str
...
>>> c = C()
>>> c.__class__
<class 'str'>
Другие вопросы по тегам