2010-05-21 6 views
1

Je veux être en mesure d'appeler une fonction globale d'une classe importée, par exemplePython Comment faire une fonction inter-module?

Dans le fichier PetStore.py

class AnimalSound(object): 
    def __init__(self): 
     if 'makenoise' in globals(): 
     self.makenoise = globals()['makenoise'] 
     else: 
     self.makenoise = lambda: 'meow' 

    def __str__(self): 
     return self.makenoise() 

Puis, quand je teste dans l'interpréteur Python

>>> def makenoise(): 
... return 'bark' 
... 
>>> from PetStore import AnimalSound 
>>> sound = AnimalSound() 
>>> sound.makenoise() 
'meow' 

Je reçois un «miaou» au lieu de «aboyer». J'ai essayé d'utiliser les solutions fournies dans python-how-to-make-a-cross-module-variable sans aucune chance.

Répondre

5

Le globals() appel retourne les globals du module dans lequel l'appel est lexicalement situé; il n'y a pas de «portée dynamique» intrinsèque en Python - c'est une portée lexicale, comme à peu près toutes les langues modernes.

La bonne façon solide, pour obtenir l'effet que vous désirez est de passer explicitement à l'initialiseur de AnimalSound le appelable il est censé utiliser pour « faire du bruit »: à savoir, la classe doit être

class AnimalSound(object): 
    def __init__(self, makenoise=lambda: 'meow'): 
     self.makenoise = makenoise 

    def __str__(self): 
     return self.makenoise() 

et l'appel doit être

sound = AnimalSound(makenoise) 

Il existe des solutions possibles mais moins sonores, comme l'appelant qui passe son propre globals() (mais qui limite inutilement le nom du appelable!), ou même (frisson) communiquer via les canaux cachés li ke les autres avocats de la réponse (ce serait un désastre potentiel si vous aviez deux instantiations de AnimalSound construit selon le même principe dans deux modules séparés, etc, etc). Mais, "explicite est mieux qu'implicite", et une communication propre, sûre et ouverte mène à des architectures de système propres, sûres et robustes: je vous recommande vivement de choisir cette route.

+0

Merci! J'étais un peu en conflit sur qui donner la réponse acceptée, mais je pense que je vais aller avec vos conseils et passer explicitement dans la fonction. – Evan

+0

@Evan, bien sûr - je n'aime pas la suggestion de Ignacio de communiquer par des canaux cachés mais je comprends que cela semble plus simple (jusqu'aux premières fois que vous perdez des heures ou des jours à déboguer les effets désastreux de ces solutions "simples", ce qui peut prendre des années ou des décennies d'expérience). Bien sûr, si vous acceptez la mauvaise solution, mais que vous implémentez la bonne, vous n'aurez jamais les expériences douloureuses nécessaires pour vraiment comprendre pourquoi la bonne solution est juste ;-). –

2

La portée "globale" dans Python est la portée du module.

import PetStore 

PetStore.makenoise = makenoise 
Questions connexes