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

2024-05-29 06:00:01 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我有这些文件(示例.py)在这个文件中,我导入了两个类。你知道吗

示例.py

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

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

内部汽车.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

目录.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

当我运行示例.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\u汽车时,来自Class\u目录的db混音了。 当我把Class\u目录放在Class\u汽车前面时,它就解决了,但我想知道如何正确地解决。你知道吗


更新:

多亏亚当·斯密才发现了这个问题。我得把这个文件改成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

Tags: pyselfnonemakedefmysqlargsquery
1条回答
网友
1楼 · 发布于 2024-05-29 06:00:01

这就是发生的事情。调用class_automobile = Class_Automobile()时,将创建一个新的Class_Automobile实例,并对该实例调用__init__方法。在__init__内您正在呼叫Pdo_Mysql('host', 'user', 'password', 'db')Pdo_Mysql.__new__被调用,Pdo\u Mysql作为cls变量,('host', 'user', 'password', 'db')作为args变量。因为这是第一次请求Pdo_Mysql对象,所以类变量__instanceNone,所以运行super调用,并在Pdo_Mysql.__instance变量上设置结果。这是班级作业。然后返回这个实例。如果你看看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 and 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 and kwargs。实例变量被设置为新值。所以现在实例class_automobileclass_catalog有一个__pdo_mysql_intern变量指向同一个实例,并且该实例的主机、用户、密码和数据库都设置为初始化实例时使用的最后一个参数。你知道吗

现在有一个可能的解决方案。。。你知道吗

似乎您正在尝试进行某种连接共享,这样就不会为每个连接到数据库的对象打开新的连接。但是,您只允许一个Pdo_Mysql实例存在。这意味着您不能连接到多个数据库并且只能作为单个用户。你知道吗

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

更进一步,我建议您不要使用__new__来创建单例,而是在pdo中创建一个helper方法_mysql.py版本叫get_conenction什么的。让它使用相同的4个参数,它可以检查实例池中是否有匹配的实例,并返回现有连接或创建新连接。你知道吗

相关问题 更多 >

    热门问题