51 votes

Une simple différence dans les noms de variables Python3 peut-elle modifier le mode de fonctionnement du code?

Ce code ...

 class Person:
    num_of_people = 0

    def __init__(self, name):
        self.name = name
        Person.num_of_people += 1

    def __del__(self):
        Person.num_of_people -= 1

    def __str__(self):
        return 'Hello, my name is ' + self.name

cb = Person('Corey')
kb = Person('Katie')
v = Person('Val')
 

Produit l'erreur suivante ...

 Exception AttributeError: "'NoneType' object has no attribute 'num_of_people'" in <bound method Person.__del__ of <__main__.Person object at 0x7f5593632590>> ignored
 

Mais ce code ne le fait pas.

 class Person:
    num_of_people = 0

    def __init__(self, name):
        self.name = name
        Person.num_of_people += 1

    def __del__(self):
        Person.num_of_people -= 1

    def __str__(self):
        return 'Hello, my name is ' + self.name

cb = Person('Corey')
kb = Person('Katie')
vb = Person('Val')
 

La seule différence que je vois est le dernier nom de variable est "vb" vs. "v".

Je suis en train d’appuyer Python et je travaille actuellement sur le sujet de la POO.

59voto

Martijn Pieters Points 271458

Oui, mais il n'est pas tellement le nom de la variable qui provoque cela, pas directement.

Quand Python sorties, tous les modules sont également supprimés. La façon dont les modules sont nettoyés à l'est par la définition de toutes les variables globales dans un module d' None (de sorte que ces références ne font plus référence à des objets d'origine). Ceux globales sont clés dans un dictionnaire d'objet, et que les dictionnaires sont commandés de manière arbitraire, le fait de renommer une variable peut changer l'ordre dans lequel les variables sont effacées.

Lorsque vous avez renommé v de vb,- vous changé l'ordre dans lequel les variables sont effacées, et maintenant, Person est désactivée dernier.

Une façon de contourner est d'utiliser type(self).num_of_people -= 1 dans la __del__ méthode de:

def __del__(self):
    type(self).num_of_people -= 1

parce que l'instance aura toujours une référence à la classe, ou de tester si Person n'est pas défini à l' None:

def __del__(self):
    if Person is not None:
        Person.num_of_people -= 1

Deux remarques:

  • Disponible 3.4 ne fixe plus globals None (dans la plupart des cas), conformément à la Sécurité de l'Objet de Finalisation; voir PEP 442.

  • Disponible 3.3 s'applique automatiquement une étude randomisée de hachage de sel à l' str clés utilisées dans un globals dictionnaire; cela rend le comportement que vous avez observé encore plus aléatoire, simplement ré-exécution de votre code plusieurs fois peut ou peut ne pas déclencher le message d'erreur.

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