2009-08-16 8 views
53

(Escrito en terminal de Python)¿Por qué no puede agregar atributos al objeto en python?

>>> o = object() 
>>> o.test = 1 

Traceback (most recent call last): 
    File "<pyshell#45>", line 1, in <module> 
    o.test = 1 
AttributeError: 'object' object has no attribute 'test' 
>>> class test1: 
    pass 

>>> t = test1() 
>>> t.test 

Traceback (most recent call last): 
    File "<pyshell#50>", line 1, in <module> 
    t.test 
AttributeError: test1 instance has no attribute 'test' 
>>> t.test = 1 
>>> t.test 
1 
>>> class test2(object): 
    pass 

>>> t = test2() 
>>> t.test = 1 
>>> t.test 
1 
>>> 

¿Por qué no se oponga le permiten añadir atributos a ella?

Respuesta

38

en cuenta que una instancia object no tiene __dict__ atributo:

>>> dir(object()) 
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__'] 

un ejemplo para ilustrar este comportamiento en una clase derivada:

>>> class Foo(object): 
...  __slots__ = {} 
... 
>>> f = Foo() 
>>> f.bar = 42 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'Foo' object has no attribute 'bar' 

Citando de los docs en slots:

[...] La declaración __slots__ toma s una secuencia de variables de instancia y reserva suficiente espacio en cada instancia para mantener un valor para cada variable. El espacio se guarda porque __dict__ no se crea para cada instancia.

EDITAR: Para responder a ThomasH por los comentarios, la clase de prueba de OP es una clase "antigua". Proveedores:

>>> class test: pass 
... 
>>> getattr(test(), '__dict__') 
{} 
>>> getattr(object(), '__dict__') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'object' object has no attribute '__dict__' 

y se dará cuenta de que hay una instancia __dict__. La clase de objeto puede no tener un __slots__ definido, pero el resultado es el mismo: la falta de un __dict__, que es lo que impide la asignación dinámica de un atributo. He reorganizado mi respuesta para aclarar esto (mueva el segundo párrafo a la parte superior).

+2

Entonces, está diciendo que la clase * object * usa \ _ \ _ slots \ _ \ _ de una forma u otra, para evitar la asignación de miembros de la instancia. ¿Es esto una suposición o un hecho (es decir, está en la implementación de * objeto *)? Porque la mera ausencia de \ _ \ dict \ _ \ _ de una instancia * object * no es indicativa. Las instancias de la clase OP * test1 * muestran la misma falta \ _ \ _ dict \ _ \ _ cuando se llama con dir(), pero permiten la asignación de los miembros de la instancia. – ThomasH

+1

@ThomasH, consulte la nota que agregué a la respuesta. – ars

3

Buena pregunta, mi conjetura es que tiene que ver con el hecho de que object es un incorporado/extensión tipo.

>>> class test(object): 
... pass 
... 
>>> test.test = 1 
>>> object.test = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't set attributes of built-in/extension type 'object' 

IIRC, esto tiene que ver con la presencia de un atributo __dict__ o, más correctamente, setattr() voladura cuando el objeto no tiene un atributo __dict__.

Cuestiones relacionadas