2010-09-04 2 views
2

Я новичок в python, и я читал, что с помощью global передавать переменные другим функциям считается noobie, а также плохой практикой. Я хотел бы отказаться от использования глобальных переменных, но я не уверен, что делать вместо этого.Альтернатива передаче глобальных переменных вокруг классов и функций

Прямо сейчас у меня есть пользовательский интерфейс, который я создал в wxPython как отдельный класс, и у меня есть другой класс, который загружает настройки из файла .ini. Поскольку настройки в пользовательском интерфейсе должны совпадать с настройками в .ini, как мне передать эти значения? Я мог бы использовать что-то вроде: Settings = Settings(), а затем определить переменные как-то вроде self.settings1, но тогда мне нужно было бы сделать Settings глобальной переменной, чтобы передать его моему классу интерфейса (которого бы не было, если бы я назначил в нем main()).

Итак, каков правильный и путинский способ обхода этих переменных?

Редактировать: Вот код, с которым я работаю, и я пытаюсь заставить его работать, как пример Алексея Мартелли. Следующий код сохраняется в Settings.py:

import ConfigParser 

class _Settings(): 
    @property 
    def enableautodownload(self): return self._enableautodownload 
    def __init__(self): 
     self.config = ConfigParser.ConfigParser() 

     self.config.readfp(open('settings.ini')) 
     self._enableautodownload=self.config.getboolean('DLSettings', 'enableautodownload') 

settings = _Settings() 

Всякий раз, когда я пытаюсь обратиться к Settings.settings.enableautodownload из другого файла я получаю: AttributeError: 'module' object has no attribute 'settings'. Что я делаю не так?

Редактировать 2: Не обращайте внимания на проблему, я перепечатал код, и теперь он работает, поэтому он должен быть простой ошибкой орфографии или синтаксиса.

+0

Есть случаи, когда хорошо использовать глобальные переменные, где общность прохождения вокруг объекта повсюду перевешивается неудобствами. Вы должны избегать этого, когда начинаете, пока не почувствуете, когда это уместно. –

+0

выглядит как правильный импорт, должен быть 'from Settings import setting ', тогда вы можете использовать его, например, как' print settings.enableautodownload'. – flow

ответ

4

Альтернативы global переменных много - в основном:

  • явные аргументы функции, классы, призванные создать одну из их, например, и т.д. (обычно это ярчайший, так как это делает зависимость наиболее явным , когда это возможно и не слишком повторяется);
  • переменные экземпляра объекта, когда функции, которые нуждаются в доступе к этим значениям, являются методами на этом же объекте (это тоже нормально, и разумный способ использования ООП);
  • «Функции доступа», которые предоставляют значения (или объект, который имеет атрибуты или свойства для значений).

Каждые из них (особенно первых и третьих из них) является особенно полезным для значений, чьи имена должны не быть повторно связаны всем и каждым, но только доступ. По-настоящему большая проблема с global заключается в том, что он обеспечивает «скрытый канал связи» (не в криптографическом смысле, а в буквальном: очевидно, отдельные функции могут фактически зависящими друг от друга, влияющими друг на друга, посредством глобальных значений, которые не являются «очевидный» из подписи функций - это делает код трудным для тестирования, отладки, поддержки и понимания).

Для вашей конкретной проблемы, если вы никогда не используете оператор global, а скорее получите доступ к настройкам «только для чтения» извне (и вы можете обеспечить более полное использование атрибутов этого объекта только для чтения) !), то доступ к «доступным только для чтения» будет выполняться на одном экземпляре на уровне модуля, сделанного один раз, а затем не изменен, не так уж плохо. То естьВ каком-то модуле foo.py:

class _Settings(object): 
    @property 
    def one(self): return self._one 
    @property 
    def two(self): return self._two 
    def __init__(self, one, two): 
     self._one, self._two = one, two 
settings = _Settings(23, 45) 

и из других стран, import foo затем просто получить доступ к foo.settings.one и foo.settings.two по мере необходимости. Обратите внимание, что я назвал класс одним лидирующим подчеркиванием (точно так же, как два атрибута экземпляра, лежащие в основе свойств только для чтения), чтобы предположить, что он не предназначен для использования из «внешнего» модуля - только объект settings (нет никакого принуждения), но любой пользователь, нарушающий такую ​​запрашиваемую конфиденциальность, является, очевидно, единственной стороной, ответственной за все возможные хаос :-).

+0

Спасибо, например, но я не могу заставить его работать над моим кодом. Я отредактировал его в вопросе, так что вы можете сказать мне, что я делаю неправильно? – FlowofSoul

+0

@Flowof, 'print Settings .__ file__' перед тем, как вы начнете пытаться использовать' Settings.settings' из другого места, чтобы подтвердить * what * именно то, что вы импортировали под этим своеобразным именем (имена модулей-членов часто дают проблемы в не зависящих от регистрационных файлах файловых системах, таких как обычные Windows и некоторые Mac, поэтому теперь они сильно обескуражены в пользу всех строчных). В удивительном случае, когда вы действительно импортировали нужный файл, добавьте 'print dir (Settings)', чтобы увидеть, что именно ** ** определено в нем. Измените свой вопрос, чтобы предоставить эту важную информацию. –

+0

Все правильно импортировалось, поэтому я просто перепечатал код и теперь работает. Спасибо за вашу помощь. – FlowofSoul

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