所以在python中对单身人士的讨厌很多。我通常看到单身人士通常没有好处,但是那些有副作用的东西,比如使用/查询数据库呢?为什么我可以为每个简单的查询创建一个新实例,当我可以重新使用已经再次设置的当前连接时?什么是pythonic方法/替代呢?
谢谢!
答案 0 :(得分:6)
通常,您有某种对象表示使用数据库的对象(例如,MyWebServer
的实例),并且您将数据库连接作为该对象的成员。
如果您将所有逻辑放在某种函数中,请将该函数的连接局部化。 (这在许多其他语言中并不常见,但在Python中,通常有很好的方法可以在单个生成器函数中包含多阶段有状态工作。)
如果您将所有数据库内容分散到各处,那么只需使用全局变量而不是单例。是的,全局变量很糟糕,但单身人士同样糟糕,而且更复杂。在一些情况下,它们很有用,但非常罕见。 (对于其他语言来说,这不一定是正确的,但它适用于Python。)摆脱全局的方法是重新考虑你的设计。你有效地使用模块作为(单例)对象是很有可能的,如果你仔细考虑,你可能会想出一个好的类或函数来包装它。
显然只是将所有的全局变量都移动到类属性中,而@classmethod
只是在不同的命名空间下给你全局变量。但是将它们移动到实例属性和方法是另一回事。这会给你一个你可以传递的对象 - 如果有必要的话,你可以拥有一个对象(或者在某些情况下甚至可以为0),附加一个锁,序列化等等。
在许多类型的应用程序中,您仍然会得到一个单独的实例 - 每个Qt GUI应用程序只有一个MyQApplication
,几乎每个Web服务器只有一个MyWebServer
,无论你怎么称呼它,它实际上是一个单身人士或全球人。如果你愿意,你可以把所有东西都移到那个神对象的属性中。
但仅仅因为你可以这样做并不意味着你应该。你仍然有函数参数,局部变量,每个模块中的全局变量,其他(非巨石)类以及它们自己的实例属性等等,你应该使用适合每个值的任何东西。
例如,假设您的MyWebServer
为每个连接到您的新客户端创建一个新的ClientConnection
实例。只要他们想要执行SQL查询,您就可以使连接写入MyWebServer.instance.db.execute
...但您也可以将self.db
传递给ClientConnection
构造函数,然后每个连接只执行self.db.execute
}。那么,哪一个更好?好吧,如果你采用后一种方式,它会使你的代码更容易扩展和重构。如果要在4个数据库之间进行负载平衡,则只需在一个位置更改代码(MyWebServer
初始化每个ClientConnection
)而不是100(每次ClientConnection
访问时数据库)。如果要将单片Web应用程序转换为WSGI容器,则除了构造函数之外,您不必更改任何ClientConnection
代码。等等。
答案 1 :(得分:1)
如果你正在使用面向对象的方法,那么abamet关于将数据库连接参数作为类属性附加的建议对我来说是有意义的。然后,该类可以建立单个数据库连接,例如,该类的所有方法都称为self.db_connection
。
如果您不使用面向对象的方法,则单独的数据库连接模块可以提供功能样式的等效方法。将模块用于建立数据库连接,只需将模块导入到您想要使用它的任何位置。然后,您的代码可以将连接称为db.connection
,例如。由于模块实际上是单例,并且模块代码仅在第一个导入上运行,因此每次都将重新使用相同的数据库连接。