62 votes

Pourquoi ne peut-on pas ajouter des attributs à un objet en python ?

(Écrit en shell 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
>>>

Pourquoi l'objet ne permet-il pas d'y ajouter des attributs ?

47voto

ars Points 35803

Notez qu'un object L'instance n'a pas __dict__ attribut :

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

Un exemple pour illustrer ce comportement dans une classe dérivée :

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

Citation de la documentation sur slots :

[...] Le site __slots__ prend une séquence de variables d'instance et réserve juste assez d'espace dans chaque instance pour contenir une valeur pour chaque variable. L'espace est économisé car __dict__ n'est pas créé pour chaque instance.

EDIT : Pour répondre à ThomasH dans les commentaires, la classe d'essai du PO est une classe "à l'ancienne". Essayez :

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

et vous remarquerez qu'il y a un __dict__ instance. La classe d'objets peut ne pas avoir de __slots__ défini, mais le résultat est le même : l'absence d'une __dict__ C'est ce qui empêche l'affectation dynamique d'un attribut. J'ai réorganisé ma réponse pour rendre cela plus clair (déplacer le deuxième paragraphe vers le haut).

4voto

D.Shawley Points 30324

Bonne question, je pense que cela a à voir avec le fait que object es un Type d'intégration/extension .

>>> 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, cela a à voir avec la présence d'une __dict__ ou, plus correctement, setattr() explosant quand l'objet n'a pas de __dict__ attribut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X