Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
DB Connections类作为Python中的单例_Python_Database_Singleton - Fatal编程技术网

DB Connections类作为Python中的单例

DB Connections类作为Python中的单例,python,database,singleton,Python,Database,Singleton,因此,python中有很多对单例的憎恨。我通常认为,拥有一个单例通常是不好的,但是那些有副作用的东西呢,比如使用/查询数据库?为什么我要为每个简单的查询创建一个新的实例,而我可以重用已经设置好的现有连接?什么是pythonic方法/替代方法 谢谢大家! 通常,您有某种对象表示使用数据库的对象(例如,MyWebServer的实例),并且您将数据库连接作为该对象的成员 如果您将所有逻辑都放在某个函数中,则将连接设置为该函数的本地连接。(这在许多其他语言中并不常见,但在Python中,通常有很好的方法

因此,python中有很多对单例的憎恨。我通常认为,拥有一个单例通常是不好的,但是那些有副作用的东西呢,比如使用/查询数据库?为什么我要为每个简单的查询创建一个新的实例,而我可以重用已经设置好的现有连接?什么是pythonic方法/替代方法


谢谢大家!

通常,您有某种对象表示使用数据库的对象(例如,
MyWebServer
的实例),并且您将数据库连接作为该对象的成员

如果您将所有逻辑都放在某个函数中,则将连接设置为该函数的本地连接。(这在许多其他语言中并不常见,但在Python中,通常有很好的方法将多阶段有状态工作封装到单个生成器函数中。)

如果所有的数据库都分散在各个地方,那么只需使用一个全局变量而不是单个变量。是的,全局性是不好的,但单身也同样不好,而且更复杂。在一些情况下,它们是有用的,但非常罕见。(对于其他语言来说,这不一定是正确的,但对于Python来说是正确的。)摆脱全局性的方法是重新考虑您的设计。很有可能您正在有效地将模块用作(单例)对象,如果您仔细考虑,您可能会想出一个好的类或函数来封装它


显然,将所有全局变量移动到类属性和
@classmethod
s中只是在不同的命名空间下为您提供全局变量。但将它们转移到实例属性和方法中则是另一回事。这将为您提供一个可以传递的对象,如果需要,还可以提供一个对象,您可以拥有其中的2个(在某些情况下甚至可能是0个),将锁附加到该对象,并对其进行序列化,等等

在许多类型的应用程序中,您仍然会得到一个单一的实例,每个Qt GUI应用程序都有一个
MyQApplication
,几乎每个web服务器都有一个
MyWebServer
,等等。无论您如何称呼它,这实际上是一个单一的或全局的实例。如果你想的话,你可以把所有的东西都移动到上帝物体的属性中

但仅仅因为你可以这样做并不意味着你应该这样做。您仍然拥有函数参数、局部变量、每个模块中的全局变量、具有自己实例属性的其他(非megalithic)类等,您应该使用适合每个值的任何东西


例如,假设您的
MyWebServer
为连接到您的每个新客户端创建一个新的
ClientConnection
实例。您可以让连接在需要执行SQL查询时写入
MyWebServer.instance.db.execute
,但您也可以将
self.db
传递给
ClientConnection
构造函数,然后每个连接只执行
self.db.execute
。那么,哪一个更好呢?如果采用后一种方法,那么代码的扩展和重构就会容易得多。如果要在4个数据库之间实现负载平衡,只需在一个位置(其中
MyWebServer
初始化每个
ClientConnection
)而不是100(每次
ClientConnection
访问数据库时)更改代码。如果您想将单片web应用程序转换为WSGI容器,则无需更改任何
ClientConnection
代码,但可能需要更改构造函数。等等。

如果您使用的是面向对象的方法,那么abamet关于将数据库连接参数作为类属性附加的建议对我来说是有意义的。然后,该类可以建立单个数据库连接,例如,该类的所有方法都将其称为
self.db_connection


如果您没有使用面向对象的方法,那么一个单独的数据库连接模块可以提供与之相当的功能样式。将一个模块用于建立数据库连接,只需在您想使用它的任何地方导入该模块即可。然后,您的代码可以将连接称为
db.connection
,例如。由于模块实际上是单例的,并且模块代码仅在第一次导入时运行,因此每次都将重新使用相同的数据库连接。

sort of app=class.webapp();app.dbconn=class.dbconn()?最终这真的与单例完全不同吗?@JeffryFroman我使用模块的问题是,我喜欢具有某种全局但仍然是单例类内部状态的想法。例如,您将如何解决DB连接参数的“存储”问题?将它们放在同一个模块中会有点混乱,而将它们放在像模块一样的一般设置中会使数据库模块严格依赖于该模块。