94 votes

Ne peut pas définir les attributs de la classe d'objet

Donc, j'ai été jouer avec Python tout en répondant à cette question, et j'ai découvert que ce n'est pas valide:

o = object()
o.attr = 'hello'

en raison d'un AttributeError: 'object' object has no attribute 'attr'. Cependant, avec toute la classe héritée de l'objet, il est valide:

class Sub(object):
    pass

s = Sub()
s.attr = 'hello'

L'impression s.attr affiche "bonjour" comme prévu. Pourquoi est-ce le cas? Ce qui, dans le langage Python spécification indique que vous ne pouvez pas assigner des attributs à la vanille objets?

138voto

Alex Martelli Points 330805

Une instance de object ne pas porter autour d'un __dict__ -- si elle l'était, avant l'horrible circulaire dépendance problème (depuis dict, comme la plupart de tout le reste, hérite de l' object;-), ce serait selle chaque objet en Python avec un dict, ce qui voudrait dire une surcharge de nombreux octets par l'objet qui, actuellement, n'ont pas ou ont besoin d'une dict (essentiellement, tous les objets qui n'ont pas arbitrairement assignables attributs n'ont pas ou ont besoin d'un dict).

Par exemple, à l'aide de l'excellent pympler projet (vous pouvez l'obtenir via svn à partir d' ici), nous pouvons faire des mesures...:

>>> from pympler import asizeof
>>> asizeof.asizeof({})
144
>>> asizeof.asizeof(23)
16

Vous ne voudriez pas que chaque int prendre 144 octets au lieu de seulement 16 ans, non?-)

Maintenant, lorsque vous effectuez une classe héritant de quoi que ce soit), les choses changent...:

>>> class dint(int): pass
... 
>>> asizeof.asizeof(dint(23))
184

...l' __dict__ est maintenant ajoutée (et en plus, un peu plus de surcharge) -- une dint instance peut avoir des attributs, mais vous devez payer assez d'un coût de l'espace pour que la flexibilité.

Donc si vous voulais ints avec juste un attribut supplémentaire foobar...? C'est rare de besoin, mais Python offre un mécanisme spécial pour les fins de la...

>>> class fint(int):
...   __slots__ = 'foobar',
...   def __init__(self, x): self.foobar=x+100
... 
>>> asizeof.asizeof(fint(23))
80

...pas tout à fait aussi minuscule qu'un int, vous l'esprit! (ou même les deux ints, l'une de la self le self.foobar -- le second peut être réaffectés), mais certainement beaucoup mieux qu'un dint.

Lorsque la classe a l' __slots__ attribut spécial (une séquence de chaînes de caractères), puis l' class déclaration (plus précisément, la valeur par défaut métaclasse, type) n'a pas d'équiper chaque instance de cette classe avec un __dict__ (et donc la capacité à avoir des attributs), juste un corps fini, ensemble rigide de "slots" (essentiellement les endroits qui peuvent tenir une référence à un objet) avec les prénoms.

En échange de la perte de flexibilité, vous gagnez beaucoup d'octets par exemple (probablement de sens que si vous avez des milliards de cas gallivanting autour, mais, il y sont des cas d'utilisation pour que).

17voto

Antti Haapala Points 11542

Si vous avez besoin de trucs attributs d'un objet, Python 3.3,+, vous pouvez utiliser types.SimpleNamespace.

4voto

Unknown Points 22789

Il est tout simplement en raison de l'optimisation.

Dicts sont relativement importantes.

>>> import sys
>>> sys.getsizeof((lambda:1).__dict__)
140

La plupart (peut-être) des classes qui sont définies dans C n'ont pas de dict pour l'optimisation.

Si vous regardez le code source , vous verrez qu'il existe de nombreuses vérifications pour voir si l'objet a un dict ou pas.

2voto

Smashery Points 13208

Donc, en enquêtant sur ma propre question, j'ai découvert cela sur le langage Python: vous pouvez hériter de choses, comme int, et vous voyez le même comportement:

>>> class MyInt(int):
       pass

>>> x = MyInt()
>>> print x
0
>>> x.hello = 4
>>> print x.hello
4
>>> x = x + 1
>>> print x
1
>>> print x.hello
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
AttributeError: 'int' object has no attribute 'hello'

Je suppose que l'erreur à la fin, c'est parce que l'ajout d'une fonction qui retourne un int, donc j'aurais besoin de surcharger des fonctions comme __add__ et pour conserver mes attributs personnalisés. Mais tout cela maintenant fait sens pour moi (je pense), quand je pense à "objet" comme "int".

0voto

Ryan Points 7423

C'est parce que l'objet est un "type", et non pas une classe. En général, toutes les classes qui sont définies dans le C des extensions (comme tous les construit dans les types de données, et des trucs comme des tableaux numpy) ne permettent pas plus de l'arbitraire des attributs.

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