2014-11-19 3 views
0

У меня есть класс Config(), который загружает параметры конфигурации. Я создаю экземпляр этого класса cfg.
Тогда у меня есть много классов A, B, C, которые должны соответствовать только членов cfg.глобальная переменная доступа (только для чтения) в классе метод

from mylib.config import * 
from mylib.A import * 
from mylib.B import * 
from mylib.C import * 

cfg = Config(filename) 
a = A() 
a.do_things() 

и, например, в конструкторе у меня есть:

def __init__(self): 
    self.name = cfg.name 

проблема заключается в том, что я получаю во время выполнения «NameError: название„CFG“не определен» на линии self.name = CFG .name

Я сначала подумал, что это то, что я импортировать mylib.A, mylib.B и mylib.C, прежде чем объявить CFG так что я переехал

cfg = Config(filename) 

перед импортом mylib.A ... B ... C. Но все та же ошибка.

Возможные решения:
1. передача объекта «CFG» в качестве аргумента, но я должен был бы изменить подпись для всех методов во всех классах A, B, C, и я чувствую, что это не чистый, так как он умножает тот же аргумент accross все методы.
2. создать частный член _cfg для классов A, B, C. Лучше, но не очень приятно снова, данные умножаются
3. поместите определение класса + объявление экземпляра в один файл и импортируйте его в mylib.A, mylib. B и mylib.C: AFAISI это лучшее решение, но все же не мой вкус, потому что я смешиваю определение класса и объявление экземпляра, и мне нравится иметь только определения классов в файлах классов.
4. Чтобы избежать определения класса и инициализации в том же файле, Я могу создать «init.py»

from mylib.config import * 
cfg = Config(filename) 

, а затем импортировать в INIT mylib.A, mylib.B и mylib.C ... но у меня уже есть файл инициализации, с функциями журнала и так Config конструктора использования эти функции создают циклические проблемы с импортом (init.py импортируется в файл объявления класса mylib.config.py, а mylib.config импортируется в init.py), чтобы избежать этого, у меня должны быть init.py и init_config.py для пример.

Нет ничего лучше/чище/проще?

ответ

0

Как насчет, в пределах mylib.config, вы создаете функцию initialize, которая создает глобальный объект конфигурации.

config_obj = None 
#todo: pick a better name for this 

class Config: 
    def __init__(self, filename): 
     pass 
     #todo: definition goes here. 

def initialize(filename): 
    global config_obj 
    config_obj= Config(filename) 

Затем в основной файл, вы вызываете эту функцию, прежде чем сделать что-нибудь с модулями A B или C.

from mylib.config import * 
from mylib.A import * 
from mylib.B import * 
from mylib.C import * 

initialize(filename) 
a = A() 
a.do_things() 

Не забудьте import config в любых модулей необходимо обратиться к config_obj.

#mylib.a 
import config 

class Whatever: 
    def __init__(self): 
     self.name = config.cfg_obj.name 

Обратите внимание, что вы не должны заменить import config с from config import *, потому что тогда скопировать по cfg_obj не получить правильно обновляется, когда основной файл вызывает initialize.


Если вам не нравится ваши модули класса, имеющие функции или глобальные переменные, вы можете сделать initialize статический метод класса Config, который возвращает одноэлементный экземпляр Config.

#singleton Config class. Only one instance of it should ever exist. 
#Users, please don't call Config(filename). use get_instance() instead. 
class Config: 
    instance = None 
    def __init__(self, filename): 
     pass 
     #definition goes here... 

    @staticmethod 
    def initialize(filename): 
     if Config.instance is not None: 
      msg = "singleton Config has already been initialized" 
      raise Exception(msg) 
     #this is the only place Config(filename) should ever be called. 
     Config.instance = Config(filename) 
     return Config.instance 

    @staticmethod 
    def get_instance(): 
     if Config.instance is None: 
      msg = "can't get instance because it hasn't been initialized yet" 
      raise Exception(msg) 
     return Config.instance 

(Там может быть лучше способы сделать singleton in Python я просто пошел с простым подходом для иллюстративных целей.).

Затем инициализации в главном файле:

from mylib.config import * 
from mylib.A import * 
from mylib.B import * 
from mylib.C import * 

Config.initialize(filename) 
a = A() 
a.do_things() 

И получить экземпляр в модулях:

#mylib.a 
import config 

class Whatever: 
    def __init__(self): 
     self.name = config.Config.get_instance().name 

(При таком подходе я тонкий k вы можете from config import * в модулях, если хотите.)

+0

ваше предложение выглядит как мое третье решение с инкапсуляцией и «глобальным» использованием, две вещи не нужны ИМХО (я могу ошибаться) ... я пытаюсь избегайте объявления и определения смешивания в mylib.config. – comte

+0

@comte, хорошо, вы можете поместить все в классы, если используете одноэлементный шаблон. Ред. – Kevin

Смежные вопросы