Pergunta

Eu gostaria de poder fazer:

>>> 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
Foi útil?

Solução

Eu resolvi dessa maneira:

>>> 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'>

Outras dicas

O Python 2 não possui uma hierarquia de objetos unificados (ou seja, nem tudo é descendente da classe de objeto). Qualquer coisa que faça parte dessa hierarquia pode ser tocada com via via __class__, mas aqueles que não são não podem ser modificados dessa maneira (ou realmente). Estes são chamados de "tipos" de Python e são codificados em C. exemplos de tipos são str, int, float, list, tuple, etc. Isso significa que você não pode usar os tipos da mesma maneira que as classes, por exemplo, você não pode alterar a classe de uma instância de um tipo, você não pode adicionar, remover ou modificar métodos de tipos, etc. A seguinte transcrição mostra a diferença em comportamento entre tipos como str (Construções C não codificadas, não dinâmicas) e classes que chamei de construções A e B (Construções Python de Python, mutáveis, mutáveis):

>>> 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

Apenas classes que foram definidas com um class palavra -chave poderia ser usada para __class__ atributo Atribuição:

>>> class C:
    pass

>>> class D:
    pass

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

Eu tentei assim!

>>> class C(str):
...     __class__ = str
...
>>> c = C()
>>> c.__class__
<class 'str'>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top