Python Как сделать кросс-модульную функцию? - PullRequest
1 голос
/ 21 мая 2010

Я хочу иметь возможность вызывать глобальную функцию из импортированного класса, например

В файле 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()

Затем, когда я тестирую в интерпретаторе Python

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

Я получаю «мяу» вместо «кора». Я попытался использовать решения, предоставленные в python-how-to-make-a-cross-module-variable , но безуспешно.

Ответы [ 2 ]

5 голосов
/ 21 мая 2010

Вызов globals() возвращает глобальные переменные модуля, в котором находится лексически вызов; в Python нет встроенной «динамической области видимости» - она ​​имеет лексическую область, как и почти все современные языки.

Надежный, правильный способ получить желаемый эффект - это явно передать инициализатору AnimalSound вызываемый объект, который он должен использовать для «создания шума»: то есть класс должен быть

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

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

и вызов должен быть

sound = AnimalSound(makenoise)

Существуют практичные, но менее надежные решения, например, вызывающий абонент передает свой собственный globals() (но это излишне ограничивает имя вызываемого пользователя!) Или даже (дрожь) общение по скрытым каналам, как другие сторонники ответа это было бы потенциальной катастрофой, если бы у вас было два экземпляра AnimalSound, построенных по одному и тому же принципу в двух отдельных модулях и т. д., и т. д.). Но «явный лучше, чем неявный», а чистая, безопасная, открытая связь приводит к чистым, безопасным и надежным системным архитектурам: я настоятельно рекомендую вам выбрать этот маршрут.

2 голосов
/ 21 мая 2010

"Глобальная" область видимости в Python - это область видимости модуля.

import PetStore

PetStore.makenoise = makenoise
...