del
semble avoir une certaine mémoire qui me laisse perplexe. Voir ce qui suit:
In [1]: import math
In [2]: math.cos(0)
Out[2]: 1.0
In [3]: del math.cos
In [4]: math.cos(0)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-9cdcc157d079> in <module>()
----> 1 math.cos(0)
AttributeError: module 'math' has no attribute 'cos'
Bien. Voyons ce qui se passe si nous supprimons l'ensemble du package mathématique:
In [5]: del math
In [6]: math.cos(0)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-6-9cdcc157d079> in <module>()
----> 1 math.cos(0)
NameError: name 'math' is not defined
Alors maintenant, les mathématiques ont disparu, comme prévu.
Maintenant, importons à nouveau les mathématiques:
In [7]: import math
In [8]: math.cos(0)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-9cdcc157d079> in <module>()
----> 1 math.cos(0)
AttributeError: module 'math' has no attribute 'cos'
Donc, en quelque sorte interactif python se souvient que math.cos a été supprimé spécifiquement même après que nous ayons supprimé le package mathématique entier et l'avons à nouveau importé.
Où python conserve-t-il ces connaissances? Peut-on y accéder? Peut-on le changer?
Je dirais que le paquet est toujours considéré comme importé. Donc performant import math
redéclare simplement le nom, mais avec l'ancien contenu.
Vous pouvez utiliser reload
pour vous assurer que votre module est à nouveau entier, sauf que certaines versions de python nécessitent de supprimer l'entrée dans sys.modules
également, ce qui rend l'utilisation de reload
redondante:
import math
del math.cos
del math
sys.modules.pop("math") # remove from loaded modules
import math
print(math.cos(0)) # 1.0
(cette différence entre les différentes versions de python, reload
et import
est discutée dans une question de suivi: si importlib.reload restaure un fichier supprimé) attribut dans Python 3.6? )
Un package n'est lu qu'une seule fois sur le disque, puis stocké en mémoire en tant que singleton mutable. La deuxième fois que vous l'importez, vous obtenez exactement le même singleton que vous avez précédemment importé, et il lui manque toujours son cos
. del math
supprime simplement le nom local pour celui-ci, il "n'importe pas" le paquet de Python globalement.
del math
ne supprime pas du tout le paquet, il supprime simplement nom localmath
dans le module actuel.
Comme tout autre objet, si d'autres références au module mathématique existent quelque part, il est conservé en mémoire.
Et en particulier, sys.modules
est toujours un dictionnaire de tous les modules chargés, donc au moins il y a toujours une référence.
Edit: Mais il existe un moyen de recharger un module, imp.reload
.
Malheureusement, je ne peux pas le faire fonctionner dans ce cas, le rechargement a besoin du module aléatoire (probablement pour créer une partie du fichier compilé Python), le module aléatoire a besoin de math.cos
, Et c'est parti. Même avec l'importation de random
d'abord, il n'y a pas d'erreur, mais math.cos
ne réapparaît pas; Je ne sais pas pourquoi, peut-être parce que c'est un module intégré.