Обычно у вас есть объект, представляющий объект, который использует базу данных (например, экземпляр MyWebServer
), и вы делаете соединение с базой данных членом этого объекта.
Если у вас есть вся ваша логика внутри какой-либо функции, сделайте соединение локальным для этой функции. (Это не слишком распространено на многих других языках, но в Python часто есть хорошие способы обернуть многоступенчатую работу с состоянием в одной функции генератора.)
Если у вас есть все базы данных, над местом, то просто используйте глобальную переменную вместо синглтона. Да, глобалы плохие, но одиночные игры так же плохи и сложнее. Есть несколько случаев, когда они полезны, но очень редки. (Это не обязательно верно для других языков, но это для Python.) И способ избавиться от глобального - это переосмыслить дизайн. Там хороший шанс, что вы эффективно использовать модуль в качестве (Singleton) объекта, и если вы думаете, через это, вероятно, можно придумать хороший класс или функцию, чтобы обернуть его в.
Очевидно просто перемещая все ваши глобальные переменные в атрибуты класса, а @classmethod
s просто дает вам глобальные переменные под другим пространством имен. Но переместить их в экземпляр атрибуты и методы - это совсем другая история. Это дает вам объект, который вы можете пройти, и, при необходимости, объект, в котором вы можете иметь 2 (или, возможно, даже 0 при некоторых обстоятельствах), присоединить блокировку, сериализацию и т. Д.
Во многих типах приложений , вы все равно получите один экземпляр чего-то - каждое приложение Qt GUI имеет ровно один MyQApplication
, почти каждый веб-сервер имеет ровно один MyWebServer
и т. д. Независимо от того, что вы называете это, это эффективно одноэлементный или глобальный. И если вы хотите, вы можете просто переместить все в атрибуты этого объекта божества.
Но только потому, что вы может это не значит, что вы должны. У вас все еще есть параметры функции, локальные переменные, глобальные переменные в каждом модуле, другие (немигалитические) классы с их собственными атрибутами экземпляра и т. Д., И вы должны использовать все, что подходит для каждого значения.
Например, ваш MyWebServer
создает новый экземпляр ClientConnection
для каждого нового клиента, который подключается к вам. Вы могли бы сделать соединения писать MyWebServer.instance.db.execute
всякий раз, когда они хотят выполнить SQL-запрос ... но вы также можете просто передать self.db
в конструктор ClientConnection
, и каждое соединение затем просто выполняет self.db.execute
. Итак, какой из них лучше? Ну, если вы это сделаете последним, это упростит ваш код и рефакторинг. Если вы хотите загрузить баланс в 4 базах данных, вам нужно всего лишь изменить код в одном месте (где MyWebServer
инициализирует каждый ClientConnection
) вместо 100 (каждый раз, когда ClientConnection
обращается к базе данных). Если вы хотите конвертировать свое монолитное веб-приложение в контейнер WSGI, вам не нужно менять какой-либо код ClientConnection
, за исключением, может быть, конструктора. И так далее.
вид приложение = class.webapp(); app.dbconn = class.dbconn()? Действительно ли это все, что отличается от синглтона в конце? – AlessandroEmm
@AlessandroMeyer: Позвольте мне отредактировать ответ на адрес. – abarnert