Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.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
将数据库驱动(非OO)python脚本转换为非数据库驱动的OO脚本_Python_Object - Fatal编程技术网

将数据库驱动(非OO)python脚本转换为非数据库驱动的OO脚本

将数据库驱动(非OO)python脚本转换为非数据库驱动的OO脚本,python,object,Python,Object,我有一些严重依赖MySQL的软件,是用python编写的,没有任何类定义。出于性能原因,并且由于数据库实际上只是用于存储和检索大量数据,我想将其转换为一个完全不使用数据库的面向对象python脚本 所以我的计划是将数据库表导出到一组文件中(不是很多——这是一个非常简单的数据库;它很大,因为它有很多行,但只有几个表,每个表只有两到三列) 然后我计划在中读取数据,并拥有一组函数,这些函数提供对数据的访问和操作 我的问题是: 是否有将一组数据库表转换为类和对象的首选方法?例如,如果我有一个包含水果的表

我有一些严重依赖MySQL的软件,是用python编写的,没有任何类定义。出于性能原因,并且由于数据库实际上只是用于存储和检索大量数据,我想将其转换为一个完全不使用数据库的面向对象python脚本

所以我的计划是将数据库表导出到一组文件中(不是很多——这是一个非常简单的数据库;它很大,因为它有很多行,但只有几个表,每个表只有两到三列)

然后我计划在中读取数据,并拥有一组函数,这些函数提供对数据的访问和操作

我的问题是:

是否有将一组数据库表转换为类和对象的首选方法?例如,如果我有一个包含水果的表,其中每个水果都有一个id和一个名称,我会有一个包含“水果”对象列表的“CollectionOfFruit”类,还是只有一个包含元组列表的“CollectionOfFruit”类?或者我只需要一份水果物品的清单

我不想添加任何额外的框架,因为我希望这些代码能够轻松地传输到不同的机器上。所以我真的只是在寻找关于如何表示可能更自然地存储在Python中的数据库表和对象中的数据的一般建议


或者,我应该读一本好书,为我指明正确的方向吗?

对此没有“一刀切”的答案——这在很大程度上取决于数据以及它在应用程序中的使用方式。如果数据和用法足够简单,您可能希望将水果存储在dict中,id作为键,其余数据作为元组。或者不是。这完全取决于情况。如果有一个指导原则的话,那就是提取应用程序的底层需求,然后根据这些需求编写代码。

您可以拥有一个带有id和name实例变量的水果类。还有一个从文件中读取/写入信息的函数,也许还有一个类变量来跟踪创建的水果(对象)的数量。通常,您希望对象与“真实世界实体”完全匹配

因为您是从数据库开始的,所以数据库也不总是具有真实世界的保真度。有些数据库设计简直糟透了

如果你的数据库有合理的水果模型,那就是你的起点。先把它弄对

“集合”可能是——也可能不是——一个人工构造,它是解决方案算法的一部分,而不是问题的真正部分。通常,集合是问题的一部分,您也应该设计这些类

然而,在其他情况下,集合是使用数据库的产物,您只需要一个简单的Python列表

还有一些时候,集合实际上是从某个唯一键值到实体的正确映射,在这种情况下,它是一个Python字典

有时,集合是从某个非唯一键值到某个实体集合的正确映射,在这种情况下,它是Python
collections.defaultdict(list)

从基本的、真实的实体开始。它们得到类定义

集合可以使用内置的Python集合,也可以需要自己的类。

在简单的情况下,让我们开始:

>>> from collections import namedtuple
>>> Fruit = namedtuple("Fruit", "name weight color")
>>> fruits = [Fruit(*row) for row in cursor.execute('select * from fruits')]
水果
相当于以下类别:

>>> Fruit = namedtuple("Fruit", "name weight color", verbose=True)
class Fruit(tuple):
        'Fruit(name, weight, color)'

        __slots__ = ()

        _fields = ('name', 'weight', 'color')

        def __new__(cls, name, weight, color):
            return tuple.__new__(cls, (name, weight, color))

        @classmethod
        def _make(cls, iterable, new=tuple.__new__, len=len):
            'Make a new Fruit object from a sequence or iterable'
            result = new(cls, iterable)
            if len(result) != 3:
                raise TypeError('Expected 3 arguments, got %d' % len(result))
            return result

        def __repr__(self):
            return 'Fruit(name=%r, weight=%r, color=%r)' % self

        def _asdict(t):
            'Return a new dict which maps field names to their values'
            return {'name': t[0], 'weight': t[1], 'color': t[2]}

        def _replace(self, **kwds):
            'Return a new Fruit object replacing specified fields with new values'
            result = self._make(map(kwds.pop, ('name', 'weight', 'color'), self))
            if kwds:
                raise ValueError('Got unexpected field names: %r' % kwds.keys())

            return result

        def __getnewargs__(self):
            return tuple(self)

        name = property(itemgetter(0))
        weight = property(itemgetter(1))
        color = property(itemgetter(2))

如果数据自然适合数据库表(“矩形数据”),为什么不将其转换为sqlite?它是可移植的——只需一个文件就可以移动数据库,而sqlite可以在任何有python的地方使用(无论如何,2.5及以上版本)。

另一种方法是使用ZODB直接持久存储对象。您所要做的唯一一件事就是从Peristent派生类,然后将从根对象开始的所有内容作为对象自动存储在该数据库中。根对象来自ZODB连接。有许多后端可用,默认为简单的文件

然后,类可以如下所示:

class Collection(persistent.Persistent):

  def __init__(self, fruit = []):
      self.fruit = fruit

class Fruit(peristent.Persistent):

  def __init__(self, name):
      self.name = name
假设您拥有根对象,则可以执行以下操作:

fruit = Fruit("apple")
root.collection = Collection([fruit])
它会自动存储在数据库中。您只需从根对象访问“collection”即可再次找到它:

print root.collection.fruit
您还可以像往常一样从例如水果派生子类

提供更多信息的有用链接:


这样,您仍然可以使用Python对象的全部功能,并且不需要通过ORM来序列化某些东西,但是您仍然有一种简单的方法来存储数据。

这里有几个要点供您考虑。如果您的数据很大,将其全部读入内存可能是浪费。如果需要对数据进行随机访问,而不仅仅是顺序访问,那么每次最多只能扫描整个文件,或者将该表读入索引内存结构(如字典)。列表仍然需要某种扫描(如果排序,则直接迭代或二进制搜索)。话虽如此,如果您不需要DB的某些功能,那么就不要使用它,但是如果您只是认为MySQL太重,那么在前面的Sqlite建议中+1。它为您提供了使用数据库时所需的大部分功能,而无需并发开销。

从对象类抽象持久性。将所有持久性逻辑放在适配器类中,并将适配器分配给对象类。比如:

class Fruit(Object):

   @classmethod
   def get(cls, id):
      return cls.adapter.get(id)

   def put(self):
      cls.adapter.put(self)

   def __init__(self, id, name, weight, color):
      self.id = id
      self.name = name
      self.weight = weight
      self.color = color


 class FruitAdapter(Object):

    def get(id):
       # retrieve attributes from persistent storage here
       return Fruit(id, name, weight, color)

    def put(fruit):
       # insert/update fruit in persistent storage here

 Fruit.adapter = FruitAdapter()
 f = Fruit.get(1)
 f.name = "lemon"
 f.put()
 # and so on...

现在,您可以构建不同的FruitAdapter对象,这些对象可以与您选择的任何持久化格式(数据库、平面文件、内存集合等)进行互操作,基本Fruit类将完全不受影响。

您甚至不必将其加载到文件中。您可以将其全部加载到内存中。