Python Membres De La Classe D'Initialisation

J'ai tout récemment lutté contre un bug dans Python. C'était une de ces stupides newbie de bugs, mais il m'a fait réfléchir sur les mécanismes de Python (je suis longtemps programmeur C++, Python). Je mettrai sur le code bogué et d'expliquer ce que j'ai fait pour le résoudre, et puis j'ai quelques questions...

Le scénario: j'ai une classe appelée, qui dispose d'un dictionnaire de données des membres, voici son code (c'est la simplification de cours):

class A:
    dict1={}

    def add_stuff_to_1(self, k, v):
        self.dict1[k]=v

    def print_stuff(self):
        print(self.dict1)

La classe à l'aide de ce code est de la classe B:

class B:

    def do_something_with_a1(self):
        a_instance = A()
        a_instance.print_stuff()        
        a_instance.add_stuff_to_1('a', 1)
        a_instance.add_stuff_to_1('b', 2)    
        a_instance.print_stuff()

    def do_something_with_a2(self):
        a_instance = A()    
        a_instance.print_stuff()            
        a_instance.add_stuff_to_1('c', 1)
        a_instance.add_stuff_to_1('d', 2)    
        a_instance.print_stuff()

    def do_something_with_a3(self):
        a_instance = A()    
        a_instance.print_stuff()            
        a_instance.add_stuff_to_1('e', 1)
        a_instance.add_stuff_to_1('f', 2)    
        a_instance.print_stuff()

    def __init__(self):
        self.do_something_with_a1()
        print("---")
        self.do_something_with_a2()
        print("---")
        self.do_something_with_a3()

Avis que tous les appels à do_something_with_aX() initialise une nouvelle "propre" de l'instance de la classe A, et imprime le dictionnaire avant et après l'ajout.

Le bug (dans le cas où vous n'avez pas compris encore):

>>> b_instance = B()
{}
{'a': 1, 'b': 2}
---
{'a': 1, 'b': 2}
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
---
{'a': 1, 'c': 1, 'b': 2, 'd': 2}
{'a': 1, 'c': 1, 'b': 2, 'e': 1, 'd': 2, 'f': 2}

Dans la deuxième initialisation de la classe A, les dictionnaires ne sont pas vides, mais commencer avec le contenu de la dernière initialisation, et ainsi de suite. Je m'attendais à démarrer "frais".

Ce qui permet de résoudre ce "bug" est évidemment d'ajouter:

self.dict1 = {}

Dans le __init__ constructeur de la classe A. Cependant, qui m'a fait me demander:

  1. Quel est le sens de la "dict1 = {}" initialisation au point de dict1 de la déclaration (première ligne en classe? Il est dénuée de sens?
  2. Quel est le mécanisme d'instanciation qui provoque la copie de la référence à partir de la dernière initialisation?
  3. Si j'ajoute "l'auto.dict1 = {}" dans le constructeur (ou tout autre membre de données), comment est-il pas d'incidence sur le dictionnaire membre de déjà initialisé instances?

EDIT: Suivant les réponses que je comprends maintenant que, par la déclaration d'un membre de données et de ne pas s'y référant dans la __init__ ou quelque part d'autre que soi.dict1, je suis pratiquement la définition de ce qu'on appelle en C++/Java une donnée membre statique. En appelant à soi-même.dict1 je fais "instance" sédentaires".

  • Vous devez utiliser la nouvelle-classes de style, et d'en tirer de l'objet.
  • la classe A n'a pas de __init__(). Avez-vous intentionnellement signifie rien, ce qui est équivalent à un vide def __init__(self): pass, d'où bien sûr il n'a pas de membres de données? Si non, veuillez corriger votre code.
InformationsquelleAutor Roee Adler | 2009-05-15