2013-04-15 2 views
9

при чтении документации на python и различных списках рассылки Я всегда читаю то, что выглядит немного как догма. Глобальных переменных следует избегать, как ад, они плохой дизайн ... ОК, почему бы и нет? Но есть ситуация с реальной жизнью, когда я не понимаю, как избежать такой картины.Как избежать глобальных переменных

Скажите, что у меня есть графический интерфейс, из которого можно загрузить несколько файлов из главного меню. Файловые объекты, соответствующие загруженным файлам, могут использоваться для полного GUI (например, средство просмотра изображений, которое отображает изображение и на котором различные действия могут выполняться с помощью различных диалогов/плагинов).

Есть ли что-то действительно не так с построением следующей конструкции:

  • Menu.py -> файл будет загружен отсюда
  • Main.py -> можно использовать загруженные файловые объекты здесь
  • Dialog1.py -> или здесь
  • Dialog2.py -> или там
  • Dialog3.py -> или там
  • ...
  • Globals.py

где Globals.py будет хранить словарь, ключ есть имя загруженных файлов и значения соответствующих объектов файлов. Затем оттуда всякая часть кода, которая нуждается в этих данных, получит доступ к ней через слабые ссылки.

Извините, если мой вопрос выглядит (или есть) глупо, но вы видите какие-либо изящные или глобальные альтернативы? Одним из способов было бы инкапсулировать загруженный словарь данных в основной класс приложения Main.py, рассматривая его как центральную часть доступа GUI. Однако это также может привести к некоторым осложнениям, так как этот класс должен быть легко доступен из всех диалогов, которые нуждаются в данных, даже если они являются необходимыми прямыми детьми.

спасибо большое за вашу помощь

+1

глобальные переменные не являются злом. Что зло использует в качестве изменяемой переменной. Глобальные переменные должны оставаться статичными и «неизменными», когда это возможно. Если вам нужно изменить содержимое словаря в файле globals.py, ничего хорошего. Кроме этого, для чтения все в порядке. – CppLearner

+0

Да, глобальные «константы» в порядке, следует избегать глобальных «переменных». – monkut

+1

ОК, я понимаю, что вы имеете в виду, но я до сих пор не вижу действительной альтернативы python для предложенного мной проекта, в котором может появляться загруженный словарь данных (новые загруженные файлы, удаленные файлы) – Eurydice

ответ

11

Глобальные переменные следует избегать, поскольку они препятствуют повторному использованию кода. Несколько виджетов/приложений могут прекрасно жить в одном и том же главном цикле. Это позволяет вам абстрагировать то, что вы сейчас думаете как единый графический интерфейс, в библиотеку, которая создает такой графический интерфейс по запросу, так что (например) одна пусковая установка может запускать несколько графических интерфейсов верхнего уровня, разделяющих один и тот же процесс.

Если вы используете глобальные переменные, это невозможно, потому что несколько экземпляров GUI будут превзойти друг друга.

Альтернативой глобальным переменным является связывание необходимых атрибутов с виджетами верхнего уровня и создание суб-виджетами, указывающими на то же самое видение верхнего уровня. Затем, например, действие в меню будет использовать виджет верхнего уровня для доступа к текущему открытому файлу, чтобы работать на нем.

+0

Я соглашусь static member variable/attribute (но не обязательно как атрибуты каждого экземпляра, если снова просто для постоянной цели чтения). Но в зависимости от требования, наличие некоторых констант не так уж плохо. Просто убедитесь, что они понимают, что Python может делать и чего не может сделать: p – CppLearner

+0

Если я получу вас правильно, такой проект будет похож на то дерево, где загруженный словарь данных будет храниться как атрибут корневого виджета верхнего уровня. Затем все виджеты приложения могут получить к нему доступ через вызов метода topLevelParent. – Eurydice

+0

У вас может быть «MainModel», в котором будут храниться имена файлов и данные верхнего уровня. С QT у вас будет основное окно, и он сохранит имена файлов и данные верхнего уровня. События для открытия и записи файлов обычно обрабатываются в объектах верхнего уровня, объекты нижнего уровня не обязательно должны знать имена файлов. – Eike

-1

Я бы управлял глобальными данными, инкапсулируя данные в одном или нескольких классах и реализуя шаблон borg для этих классов. См. Why is the Borg pattern better than the Singleton pattern in Python

+1

Пожалуйста, не рекламируйте рисунок Борга. Вся суть singleton заключается в том, что у вас есть ** одиночный ** экземпляр, таким образом сохраняя память и обеспечивая идентичное поведение. Если действительно необходимо иметь разные экземпляры в разных подклассах, есть способы сделать это, не ставя под угрозу базовое требование Singleton, чтобы иметь один экземпляр для каждого класса. – user4815162342

+3

Ни Borg, ни шаблон Singleton не устраняют основной проблемы глобальных переменных, а именно, что у вас есть одно глобальное состояние. Фактически, одноэлементный шаблон - это просто приятный интерфейс OO-стиля для общего глобального состояния, что и есть то, о чем говорит литература (без объяснения причин) OP, чтобы избежать. – user4815162342

+1

Я предпочитаю практический подход: глобальные переменные aka singleton aka borg pattern опасны только в том случае, если код пишет и читает их. Глобальный регистратор (все клиенты пишут) не является опасным, а также пул для соединений с базой данных (все клиенты читают). Это нормально, если разработчики следуют за книгами, но не должны забывать об отставании. – rocksportrocker