2013-06-21 3 views
7

Нам всем сказали, что использование from module import * - плохая идея. Однако существует ли способ импортировать подмножество содержимого module с использованием шаблона?Python: подстановочный поднабор импорт

Например:

module.py:

MODULE_VAR1 = "hello" 
MODULE_VAR2 = "world" 
MODULE_VAR3 = "The" 
MODULE_VAR4 = "quick" 
MODULE_VAR5 = "brown" 
... 
MODULE_VAR10 = "lazy" 
MODULE_VAR11 = "dog!" 
MODULE_VAR12 = "Now" 
MODULE_VAR13 = "is" 
... 
MODULE_VAR98 = "Thats" 
MODULE_VAR99 = "all" 
MODULE_VAR100 = "folks!" 

def abs(): 
    print "Absolutely useful function: %s" % MODULE_VAR1 

Очевидно, что мы не хотим использовать from module import *, потому что мы бы отменяя функцию abs. Но предположим, что мы хотели, чтобы все переменные MODULE_VAR* были доступны локально.

Проще говоря from module import MODULE_VAR* не работает. Есть ли способ сделать это?

В качестве иллюстрации я использовал 100 переменных, потому что выполнение from module import MODULE_VAR1, MODULE_VAR2, MODULE_VAR3, ..., MODULE_VAR100 было бы невероятно громоздким и не работало бы, если было добавлено больше переменных (например, MODULE_VAR101).

ответ

2

Вы можете использовать переменную __all__ для импорта определенных переменных при использовании синтаксиса import *.

mymodule.py

__all__ = [ 
    'MODULE_VAR1', 
    'MODULE_VAR2', 
    'MODULE_VAR3', 
    'MODULE_VAR4', 
    'MODULE_VAR5', 
] 

MODULE_VAR1 = "hello" 
MODULE_VAR2 = "world" 
MODULE_VAR3 = "The" 
MODULE_VAR4 = "quick" 
MODULE_VAR5 = "brown" 

def abs(): 
    print "Absolutely useful function: %s" % MODULE_VAR1 

Тогда мы можем использовать его таким образом:

from mymodule import * 
print MODULE_VAR1 # hello 
print abs # <built-in function abs> 

Когда модуль импортируется с помощью *, Python проверяет модуль для __all__ переменной, которая может отвергнуть то, что в противном случае будет считаться нормальные «общедоступные» переменные в модуле (которые будут переменными, которые не начинаются с подчеркивания), и позволяют явно определять, какие переменные являются «общедоступными». Check out this question

+0

Это замечательно! Но есть ли способ добиться такого же эффекта, если у вас нет контроля над исходным кодом модуля? – seaotternerd

+0

Извините, я неправильно понял. Я не знаю, как импортировать определенные переменные из другого модуля. Но в качестве очень простого решения вы можете создать помощника, который импортирует модуль и выполняет итерации по атрибутам модуля, чтобы извлечь нужные переменные. В вашем примере это предотвратит переопределение переменной 'abs', вы не импортируете переменные модуля, а сам модуль. Кроме того, вы * можете * импортировать переменные модуля в область действия функции, предотвращая переопределение встроенной функции 'abs'. Я думаю, что @jsbueno имеет прекрасный пример. – kuujo

+0

Я не знаю, если вы неправильно поняли - я не был тем человеком, который задал вопрос, мне было просто любопытно. Благодаря! – seaotternerd

7

Вы можете иметь вспомогательную функцию для этого - и это может быть сделано без магии:

import re 

def matching_import(pattern, module, globals): 
    for key, value in module.__dict__.items(): 
     if re.findall(pattern, key): 
      globals[key] = value 

Теперь вы можете сделать, например:

from utils import matching_import 
import constants 

matching_import("MODULE_VAR.*", constants, globals()) 

Использование globals() явно в этом способ избегает масок интроспекции кадров, которые обычно считаются вредными.

+0

Хорошее решение. +1 – kuujo