2009-12-28 8 views
0

Quand les variables fonction-locales sont-elles créées? Par exemple, dans le code suivant, le dictionnaire d1 est-il créé chaque fois que la fonction f1 est appelée ou seulement une fois lorsqu'elle est compilée?Quand les variables python locales sont-elles créées?

def f1(): 
    d1 = {1: 2, 3: 4} 
    return id(d1) 

d2 = {1: 2, 3: 4} 
def f2(): 
    return id(d2) 

Est-il plus rapide en général de définir un dictionnaire dans la portée de fonction ou de la définir globalement (en supposant que le dictionnaire est utilisé uniquement dans cette fonction). Je sais qu'il est plus lent de rechercher des symboles globaux que locaux, mais que faire si le dictionnaire est grand?

Beaucoup de code python que j'ai vu semble définir ces dictionnaires globalement, ce qui ne semble pas être optimal. Mais aussi dans le cas où vous avez une classe avec plusieurs méthodes 'encoding', chacune avec un unique (big-ish) dictionnaire de recherche, il est difficile d'avoir le code et les données réparties dans le fichier.

Répondre

2

Les variables locales sont créées lorsqu'elles sont affectées à, par exemple, pendant l'exécution de la fonction.

Si chaque exécution de la fonction nécessite (et ne modifie pas! -) la même dict, la créer une fois, avant que la fonction ne soit jamais appelée, est plus rapide. Comme alternative à une variable globale, un argument faux avec une valeur par défaut est même (légèrement) plus rapide, car il est accessible aussi vite que une variable locale, mais aussi créé une seule fois (à def fois):

def f(x, y, _d={1:2, 3:4}): 

I J'utilise le nom _d, avec un trait de soulignement, pour indiquer qu'il s'agit d'un détail d'implémentation privée de la fonction. Néanmoins, il est un peu fragile, car un call maladroit pourrait passer accidentellement et par erreur trois arguments (le troisième serait lié comme _d dans la fonction, causant probablement des bogues), ou le corps de la fonction pourrait altérer _d, donc ceci est seulement recommandé comme une optimisation à utiliser lorsque le profilage révèle que c'est vraiment nécessaire. Une dictée globale est également sujette à des modifications erronées, donc, même si elle est plus rapide que de construire une dictée locale à chaque appel, vous pouvez toujours choisir la dernière option pour obtenir une plus grande robustesse (bien que la solution globale tout "oops" es dans la fonction, sont l'alternative recommandée ;-).

+0

Fait sens. Recommanderiez-vous d'utiliser les attributs function/method/class pour construire paresseusement un dictionnaire lors de son premier appel? – speeedfrk

+0

@speedfrk, dans des conditions très spécifiques: la dict est vraiment coûteuse à construire, il y a une chance raisonnable que vous n'ayez jamais à la construire sur une course donnée, et vous êtes déjà dans une classe (ou une méthode), donc il y a endroit naturel pour "garer" le dict lorsqu'il est construit. –

0

Si vous regardez le désassemblage avec le module dis, vous verrez que la création et le remplissage de d1 sont effectués à chaque exécution. Étant donné que les dictionnaires sont mutables, il est peu probable qu'ils changent de sitôt, au moins jusqu'à ce qu'une bonne analyse d'échappement arrive sur les machines virtuelles Python. D'autre part, la recherche de constantes globales sera optimisée spéculativement avec la prochaine génération de machines virtuelles Python telles que unladen-swallow (la partie spéculation est qu'elles sont constantes).

+0

Bonne idée.Dans l'attente de unladen-swallow :-) – speeedfrk

0

La vitesse est relative à ce que vous faites. Si vous écrivez une application gourmande en bases de données, je doute que votre application souffrira d'une façon ou d'une autre de votre choix de variables globales ou locales. Utilisez un profileur pour être sûr. ;-)

Comme l'a noté Alex, les variables locales sont initialisées lorsque la fonction est appelée. Comme moyen facile de démontrer cela par vous-même:

import random 

def f(): 
    d = [random.randint(1, 100), random.randint(100, 1000)] 
    print(d) 

f() 
f() 
f() 
+0

Ce n'est pas tout à fait la même chose que mes exemples de dictionnaires, qui sont 'constants' - contiennent uniquement des clés et des valeurs immuables littérales, ne sont jamais mutés et ne sont pas renvoyés par la fonction. – speeedfrk

Questions connexes