Je m'attendais à ce que les éléments d'objet à l'intérieur d'autres objets python soient isolés.
Cependant, le code suivant montre que mon résultat attendu est incorrect. Il semble que python utilise une liste_éléments centrale pour tous les éléments du Groupe . Comment puis-je réparer cela?
python3 --version Python 3.5.2
Résultat
len = 4 bb2 = bb1
Version
class Item:
name = ''
def __init__(self, name):
self.name = name
class Group:
item_list = []
def __init__(self, item):
self.item_list.append(item)
g2 = Group(Item('bb1'))
g2.item_list.append(Item('bb2'))
group_list = []
group_list.append(Group(Item('aaa')))
group_list.append(g2)
group_list.append(Group(Item('ccc')))
print('len = ', len(group_list[-1].item_list))
print('bb2 = ', group_list[1].item_list[1].name)
4 Réponses :
Les variables déclarées en dehors de la méthode __init__ (dans ce cas item_list ) sont partagées entre toutes les instances d'une classe (appelées variables de classe), c'est pourquoi votre le résultat attendu est faux.
D'un autre côté, les variables à l'intérieur de __init__ n'appartiennent qu'à l'instance donnée de cette classe.
Vos variables de classe d'utilisation, qui sont des variables statiques C ++ similaires à l'intérieur des classes (c'est-à-dire que cette variable est partagée par TOUTES les instances de classe). Vous devez le mettre dans le __init__ (constructeur) pour que chaque classe crée sa propre version:
class Item:
def __init__(self, name):
self.name = name
class Group:
def __init__(self, item):
self.item_list = []
self.item_list.append(item)
# Though typically you would also have a function like this:
def add_item(self, item):
self.item_list.append(item)
g2 = Group(Item('bb1'))
g2.item_list.append(Item('bb2'))
group_list = []
group_list.append(Group(Item('aaa')))
group_list.append(g2)
group_list.append(Group(Item('ccc')))
print('len = ', len(group_list[-1].item_list))
print('bb2 = ', group_list[1].item_list[1].name)
Eh bien, tout d'abord, nous devons faire une différence entre les attributs de classe et les attributs d'instance. Un attribut de classe (comme item_list ) appartient à la classe elle-même (dans ce cas "Group"), il sera donc accessible en appelant Group.item_list code>. D'autre part, vous pouvez définir une item_list pour chaque instance de Group en définissant self.item_list = [] dans le constructeur de classe Group ( __init __ code >).
Le tableau Group.item_list sera unique pour toute la classe et sera donc adapté pour stocker les éléments que vous souhaitez partager entre les instances (comme g2 ).
Le tableau self.item_list (qui sera différent pour chaque instance de Group) contiendra des valeurs exclusivement pour l'instance elle-même, donc chaque Groupe aura sa propre liste_éléments .
Je pense que vous visez la deuxième approche (variables d'instance) donc vous devriez déplacer la définition de item_list = [] à l'intérieur du constructeur de classe.
Le résultat devrait ressembler à ceci: class Item:
def __init__(self, name):
self.name = name
class Group:
def __init__(self, item):
self.item_list = []
self.item_list.append(item)
item1 = Item("itemName")
group1 = Group(item1)
# This should print an array containing the *item1* instance
print(group1.item_list)
print(group1.item_list[0] == item1)
Les attributs instance vs classe sont traités dans d'autres réponses. Je tiens à ajouter que vous pouvez éviter d'avoir des variables d'instance partagées en utilisant un type immuable (par exemple, tuple) au lieu d'un type mutable (par exemple, liste) pour les attributs de classe. Ainsi, ils ne seront pas partagés entre les instances tout en vous permettant de définir les attributs de classe.
class Item:
name = ''
def __init__(self, name):
self.name = name
class Group:
item_list = tuple()
def __init__(self, item):
self.item_list += (item,)
Votre
liste_élémentsainsi quenomsont des variables de classe (pensez àstatiqueen C ++). Placez-les dans le constructeur, commeself.item_list = []pour en faire des variables d'instance.class Group: \ n self.item_list = []me donneNameError: le nom 'self' n'est pas défini.À l'intérieur du constructeur (c'est-à-dire à l'intérieur de
def __init__. Ne définissez rien au niveau de la classe.pour référence future: vous pouvez utiliser
id ()pour vérifier quels objets sont identiques en mémoire. Avec[id (group.item_list) pour groupe dans group_list]vous verrez que toutes les listes sont identiques.