84 votes

Créer une liste d'objets en Python

J'essaie de créer un script Python qui ouvre plusieurs bases de données et compare leur contenu. Dans le processus de création de ce script, j'ai rencontré un problème dans la création d'une liste dont le contenu est constitué d'objets que j'ai créés.

J'ai simplifié le programme en le réduisant à sa plus simple expression. Tout d'abord, je crée une nouvelle classe, j'en crée une nouvelle instance, je lui attribue un attribut et je l'écris dans une liste. Ensuite, j'attribue une nouvelle valeur à l'instance et je l'écris à nouveau dans une liste... et encore et encore...

Le problème est qu'il s'agit toujours du même objet et que je ne fais donc que modifier l'objet de base. Lorsque je lis la liste, j'obtiens une répétition du même objet, encore et encore.

Comment écrire des objets dans une liste à l'intérieur d'une boucle ?

Voici mon code simplifié

class SimpleClass(object):
    pass

x = SimpleClass
# Then create an empty list
simpleList = []
#Then loop through from 0 to 3 adding an attribute to the instance 'x' of SimpleClass
for count in range(0,4):       
    # each iteration creates a slightly different attribute value, and then prints it to
# prove that step is working
# but the problem is, I'm always updating a reference to 'x' and what I want to add to
# simplelist is a new instance of x that contains the updated attribute

x.attr1= '*Bob* '* count
print "Loop Count: %s Attribute Value %s" % (count, x.attr1)
simpleList.append(x)

print '-'*20
# And here I print out each instance of the object stored in the list 'simpleList'
# and the problem surfaces.  Every element of 'simpleList' contains the same      attribute value

y = SimpleClass
print "Reading the attributes from the objects in the list"
for count in range(0,4):
    y = simpleList[count]
    print y.attr1

Comment puis-je (ajouter, étendre, copier ou autre) les éléments de simpleList pour que chaque entrée contienne une instance différente de l'objet au lieu de toutes pointer vers le même ?

72voto

ironfroggy Points 3496

Vous faites preuve d'une incompréhension fondamentale.

Vous n'avez jamais créé d'instance de SimpleClass, car vous ne l'avez pas appelée.

for count in xrange(4):
    x = SimpleClass()
    x.attr = count
    simplelist.append(x)

Ou, si vous laissez la classe prendre des paramètres, vous pouvez utiliser une liste de compréhension.

simplelist = [SimpleClass(count) for count in xrange(4)]

58voto

Zoomulator Points 7692

Pour remplir une liste avec des instances distinctes d'une classe, vous pouvez utiliser une boucle for dans la déclaration de la liste. Le multiplicateur * liera chaque copie à la même instance.

instancelist = [ MyClass() for i in range(29)]

et d'accéder aux instances par l'intermédiaire de l'index de la liste.

instancelist[5].attr1 = 'whamma'

12voto

Daniel Naab Points 9857

Il ne devrait pas être nécessaire de recréer l'objet SimpleClass à chaque fois, comme certains le suggèrent, si vous l'utilisez simplement pour produire des données basées sur ses attributs. Cependant, vous ne créez pas réellement une instance de la classe ; vous créez simplement une référence à l'objet classe lui-même. Par conséquent, vous ajoutez une référence au même attribut de classe à la liste (au lieu de l'attribut d'instance), encore et encore.

Au lieu de :

x = SimpleClass

vous avez besoin :

x = SimpleClass()

5voto

joel.neely Points 17059

Créer une nouvelle instance à chaque fois, où chaque nouvelle instance a l'état correct, plutôt que de modifier continuellement l'état de la même instance.

Il est également possible de stocker une copie explicite de l'objet (à l'aide de l'indice sur cette page ) à chaque étape, au lieu de l'original.

3voto

Roberto Liffredo Points 15265

Si je comprends bien votre question, vous demandez un moyen d'exécuter une copie profonde d'un objet. Pourquoi ne pas utiliser copy.deepcopy ?

import copy

x = SimpleClass()

for count in range(0,4):
  y = copy.deepcopy(x)
  (...)
  y.attr1= '*Bob* '* count

Une copie profonde est une copie récursive de l'objet entier. Pour plus d'informations, vous pouvez consulter la documentation de python : https://docs.python.org/2/library/copy.html

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