gpt4 book ai didi

python - 参数更改时处理类中的实例 - Python

转载 作者:太空宇宙 更新时间:2023-11-04 05:56:17 25 4
gpt4 key购买 nike

我正在学习如何编程和处理 Python 类并发现了这个问题。

我有这个文件 (example.py),在这个文件中我导入了两个类。

example.py

..
from class_folder.automobile import Class_Automobile
from class_folder.catalog import Class_Catalog

class_automobile = Class_Automobile()
class_catalog = Class_Catalog()
..

automobile.py 中有这段代码:

from pdo_mysql import Pdo_Mysql

class Class_Automobile(object):
"""
Description
"""
__pdo_mysql_intern = None

def __init__(self):
self.__pdo_mysql_intern = Pdo_Mysql('host', 'user', 'password', 'db')
## End def init

def Validate_Make(self, make_search):
query_make = 'make_text = %s '
result = self.__pdo_mysql_intern.select('make', query_make, 'id_make', make=make_search)
return result
## End function Validate Make

catalog.py 文件中包含以下信息:

from pdo_mysql import Pdo_Mysql

class Class_Catalog(object):
"""
Description
"""
__pdo_mysql_intern = None

def __init__(self):
self.__pdo_mysql_intern = Pdo_Mysql('host', 'user', 'password', 'db2')
## End def init

最后 pdo_mysql.py 文件有这个:

    import MySQLdb, sys

class Pdo_Mysql(object):
"""
Description
"""

__instance = None
__host = None
__user = None
__password = None
__database = None
__session = None
__connection = None


def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = super(Pdo_Mysql, cls).__new__(cls,*args,**kwargs)
return cls.__instance
## End __new__

def __init__(self, host='localhost', user='root', password='', database=''):
self.__host = host
self.__user = user
self.__password = password
self.__database = database
## __init__

def _open(self):
try:
cnx = MySQLdb.connect(self.__host, self.__user, self.__password, self.__database)
self.__connection = cnx
self.__session = cnx.cursor()
except MySQLdb.Error as e:
print "Error %d: %s" % (e.args[0],e.args[1])
## End function open

def _close(self):
self.__session.close()
self.__connection.close()
## End function close

def select(self, table, where=None, *args, **kwargs):
result = None
query = 'SELECT '
keys = args
values = tuple(kwargs.values())
l = len(keys) - 1

for i, key in enumerate(keys):
query += "`"+key+"`"
if i < l:
query += ","
## End for keys

query += 'FROM %s' % table

if where:
query += " WHERE %s" % where
## End if where

self._open()
self.__session.execute(query, values)
result = [item[0] for item in self.__session.fetchall()]
self._close()
return result
## End function select

当我运行 example.py 时我遇到了这个问题,不知何故当我调用它时

validate_information = class_automobile.Validate_Make(make)

我得到了这个回应

File "/Library/Python/2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File "/Library/Python/2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
_mysql_exceptions.ProgrammingError: (1146, "Table 'db2.make' doesn't exist")

这个问题是因为当我调用 Class_Automobile 时,来自 Class_Catalog 的数据库正在混合。当我把 Class_Catalog 放在 Class_Automobile 之前就解决了,但我想知道如何正确解决。


更新:

感谢 Adam Smith 发现了这个问题。我只需更改此文件 pdo_mysql.py:

class Pdo_Mysql(object):
# all your existing definitions

def __new__(cls, *args, **kwargs):
**if not cls.__instance or not cls.__database:**
cls.__instance = super(Pdo_Mysql, cls).__new__(cls,*args,**kwargs)
return cls.__instance

最佳答案

这是正在发生的事情。当您调用 class_automobile = Class_Automobile() 时,将创建一个新的 Class_Automobile 实例,并在该实例上调用 __init__ 方法。在 __init__ 中,您正在调用 Pdo_Mysql('host', 'user', 'password', 'db')Pdo_Mysql.__new__ 被调用,Pdo_Mysql 作为 cls 变量,('host', 'user', 'password', 'db') 作为 args变量。因为这是第一次请求 Pdo_Mysql 对象,类变量 __instanceNone 所以你的 super 调用运行并且结果设置在 Pdo_Mysql.__instance 变量上。这是类(class)作业。然后您返回此实例。如果您查看 Python docs你会看到:

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked

现在您已经从 super __new__ 调用中获得了 Pdo_Mysql 的实例并返回它。 __init__ 方法将被调用,并将 args 和 kwargs 发送到 __new__。在 __init__ 中设置各种连接属性。

此时一切正常。如果您要调用您的 class_automobile 实例,它们将按您预期的那样工作。让我们看看当您创建下一个对象时会发生什么,Class_Catalog 的实例。

它以与 Class_Automobile 相同的方式开始,直到我们到达 self。 __pdo_mysql_intern = Pdo_Mysql 调用。这次当 Pdo_Mysql.__new__ 被调用时,cls.__instance 变量被设置为 Pdo_Mysql 的一个实例,所以你不会创建一个新的.但是你仍然从 __new__ 返回这个实例,所以 __init__ 方法仍然在这个实例上运行,但是有新的 args 和 kwargs。实例变量被设置为新值。所以现在实例 class_automobileclass_catalog 有一个 __pdo_mysql_intern 变量指向同一个实例并且该实例有 __host、__user、__password 和 __database 集用于初始化实例的最后一个参数。

现在讨论一种可能的解决方案...

看起来您正在尝试进行某种连接共享,因此您不会为连接到数据库的每个对象打开一个新连接。但是,您只允许一个 Pdo_Mysql 实例存在。这意味着您不能连接到多个数据库,并且只能作为一个用户连接。

您需要一个连接池(Pdo_Mysql 对象)以供选择,以便当您想要连接到另一个数据库或作为不同的用户时,您可以这样做。在您的 Pdo_Mysql 类中,您可以将 __instance = None 变量更改为 __instances = {}。使用 args 作为此字典的键,并更改 __new__ 方法以使用 args 查找实例。请注意,这忽略了 kwargs,我留给你弄清楚如何包含它们(提示,你不能使用可变对象作为字典中的键)。您还需要向 Pdo_Mysql 类添加一个 __initialized 变量。默认为 False 并在 __init__ 中将其设置为 True。这是您可以确保只在每个实例上运行一次 __init__

更进一步,我建议您不要使用 __new__ 来创建单例,而是在 pdo_mysql.py 中创建一个名为 get_conenction 或其他东西的辅助方法。让它接受相同的 4 个参数,它可以检查它的实例池中是否有任何匹配项,并返回现有连接或建立新连接。

关于python - 参数更改时处理类中的实例 - Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27607366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com