Ne peut pas définir les attributs de la classe d'objet
Donc, j'ai été jouer avec Python tout en répondant à des cette question, et j'ai découvert que ce n'est pas valide:
o = object()
o.attr = 'hello'
en raison d'une 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'
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?
Pure conjecture: La
S. Lott: Voir la première ligne de cette question. Purement de la curiosité.
Votre titre est trompeur, vous essayez de définir des attributs sur
object
type est immuable et de nouveaux attributs ne peuvent pas être ajoutés? Il semble que ça aurait plus de sens.S. Lott: Voir la première ligne de cette question. Purement de la curiosité.
Votre titre est trompeur, vous essayez de définir des attributs sur
object
des instances de classe, pas sur object
classe.OriginalL'auteur Smashery | 2009-10-07
Vous devez vous connecter pour publier un commentaire.
À l'appui de l'arbitraire affectation d'attribut, un objet a besoin d'un
__dict__
: un dict associés à l'objet, où l'arbitraire des attributs peuvent être stockées. Sinon, il n'y a nulle part où mettre de nouveaux attributs.Une instance de
object
ne pas effectuer autour d'un__dict__
-- si elle l'était, avant l'horrible circulaire dépendance problème (depuisdict
, comme la plupart de tout le reste, hérite deobject
;-), ce serait selle chaque objet en Python avec un dict, ce qui signifierait une surcharge de 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 de ici), nous pouvons faire des mesures...:Vous ne voulez pas tous les
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...:
...la
__dict__
est maintenant ajouté (et en plus, un peu plus de surcharge) -- unedint
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
int
avec juste un attribut supplémentairefoobar
...? C'est rare de besoin, mais Python offre un mécanisme spécial pour les fins de la......pas assez aussi minuscule qu'un
int
, vous l'esprit! (ou même les deuxint
s, l'une desself
et un laself.foobar
-- le second peut être réaffectés), mais certainement beaucoup mieux qu'undint
.Lorsque la classe est le
__slots__
attribut spécial (une séquence de chaînes de caractères), puis leclass
instruction (plus précisément, la valeur par défaut métaclasse,type
) ne pas é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 cas d'utilisation pour que).
Veuillez noter que les non-vide
__slots__
ne fonctionnent pas avec la longueur variable des types commestr
,tuple
, et en Python 3int
.Belle et merci! Si un objet n'ont pas
__dict__
, fait ses classes doivent avoir un__slot__
attribut?C'est une bonne explication, mais ne peut toujours pas de réponse pourquoi (ou comment)
Sub
a la__dict__
attribut d'objet et de ne pas, être queSub
hériter deobject
, comment est-ce que l'attribut (et d'autres comme__module__
) ajouté à l'héritage? Peut-être cela pourrait être une nouvelle questionUn objet
__dict__
est créé la première fois que c'est nécessaire, de sorte que le coût mémoire situation n'est pas aussi simple que leasizeof
sortie il fait regarder. (asizeof
ne sais pas comment faire pour éviter__dict__
matérialisation.) Vous pouvez voir le dict de ne pas arriver matérialisé jusqu'en cet exemple, et vous pouvez voir l'un des chemins de code responsable de__dict__
matérialisation ici.OriginalL'auteur Alex Martelli
Que d'autres answerers l'ai dit, une
object
ne dispose pas d'un__dict__
.object
est la classe de base de tous types, y comprisint
oustr
. Donc tout ce qui est fourni parobject
sera un fardeau pour eux. Même quelque chose d'aussi simple qu'un facultatif__dict__
aurait besoin d'un coup de pointeur pour chaque valeur; ce serait déchets supplémentaires de 4 à 8 octets de mémoire pour chaque objet dans le système, pour une utilité limitée.Au lieu de faire une instance d'une classe factice, en Python 3.3,+, vous pouvez (et devez) utiliser
types.SimpleNamespace
pour cela.OriginalL'auteur Antti Haapala
Il est tout simplement en raison de l'optimisation.
Dicts sont relativement importantes.
Plus (peut-être tous) les classes qui sont définies dans C n'ont pas de dict pour l'optimisation.
Si vous regardez la le code source vous verrez qu'il existe de nombreuses vérifications pour voir si l'objet a un dict ou pas.
OriginalL'auteur Unknown
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:
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 de les conserver mes attributs personnalisés. Mais tout cela maintenant fait sens pour moi (je pense), quand je pense à "objet" comme "int".OriginalL'auteur Smashery
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.
Bingo. C'est exactement la question.
OriginalL'auteur Ryan
C'est (OMI), l'une des limites fondamentales avec Python - vous ne pouvez pas ré-ouvrir des classes. Je crois que le vrai problème, cependant, est causé par le fait que les classes implémentées en C ne peuvent pas être modifiées lors de l'exécution... les sous-classes peuvent, mais pas les classes de base.
OriginalL'auteur Peter