在 Python 中构建“复杂”数据结构的最佳方式

Best way to construct a "complex" data structure in Python

提问人:George Silva 提问时间:10/28/2009 更新时间:10/28/2009 访问量:6860

问:

我需要构建一个工具,用于以最自动化的方式创建字段映射(表之间)。

交易是这样的:想象一个表被附加到另一个表上。(让我们忽略字段类型,只是一秒钟......

CREATE OR REPLACE TABLE fooA(
id,
name,
type,
foo)

CREATE OR REPLACE TABLE otherFooTable(
idFoo,
nameFoo,
spam)

我正在考虑创建这样的结构:

fieldMap = {'otherFooTable': [('idFoo','id'),('nameFoo','name'),('spam','foo')]}

我将能够使用(例如)访问它

print fieldMap['tabelax'][0][1]

这不是一个非常复杂的结构,但我在使用它时会遇到一些问题?有没有关于如何处理此类问题的建议?我需要(现在)至少存储 inputTable(我不想为映射的每个字段重复它)、inputField、outputField。没有理由存储 outputTable,因为这总是事先知道的。

非常感谢您的建议和过去的经验。

PS:也许正式的结构(如类)会更好?

谢谢

python 列表 数据结构

评论

0赞 Denis Otkidach 10/28/2009
目前尚不清楚您的结构将如何使用,而这对其设计非常重要。另外,请使用自我描述性名称,如 、 ,以使其更清晰。'table_from''table_to''id_in_table_from'
0赞 jcdyer 10/28/2009
你的问题不清楚。什么是Tabelax?这两个表有什么关系?你希望这种连接是什么?将一个表附加到另一个表是什么意思?

答:

6赞 geowa4 10/28/2009 #1

老实说,我只是从(或使用)SQLAlchemyDjango 模型中获取提示。这些是久经考验的数据表示方法。

评论

0赞 George Silva 10/28/2009
你好geowa!谢谢你的提示。但是我正在使用它来使用 ESRI 的 ArcObjects 编写一些脚本。我不想有真正的大足迹来工作,只是为了做一个简单的字段映射。谢谢你:D
1赞 Andre Miller 10/28/2009
如果您不想在磁盘上使用实际的数据库,则可以将 SQLAlchemy 与 sqlite 内存引擎一起使用。此处的教程可能是一个很好的起点:sqlalchemy.org/docs/05/ormtutorial.html
0赞 geowa4 10/28/2009
@George:如果我必须做这个项目,我可能会使用类似于 Django 的基于类的方法
0赞 Denis Otkidach 10/28/2009
为什么你认为ORM适合这么简单的任务?它将如何帮助解决从一个结构到另一个结构的映射问题?
0赞 geowa4 10/28/2009
@Denis:嗯,我的主要答案是从他们那里得到提示。创建一个对象来表示表的行。有一个构造函数来从数据库加载字段,将一些键作为参数(如 ID);然后添加保存和删除方法。这不是一个完整的 ORM 框架,但它使用了这些想法,并使使用它变得简单,这就是重点。
2赞 S.Lott 10/28/2009 #2

想想看

class Column( object ):
    def __init__( self, name, type_information=None ):
        self.name = name
        self.type_information = type_information
        self.pk = None
        self.fk_ref = None
    def fk( self, column ): 
        self.fk_ref = column

class Table( object ):
    def __init__( self, name, *columns ):
        self.name = name
        self.columns = dict( (c.name, c) for c in columns )
    def column( self, name ):
        return self.columns[ name ]

Table( "FOOA", Column( "id" ), Column( "name" ), Column( "type" ), Column( "foo" ) )

Table( "otherFooTable", Column( "idFoo" ), Column( "nameFoo" ), Column( "spam" ) )

你根本不清楚你要做什么或为什么,所以这和任何事情一样好,因为它似乎代表了你实际拥有的信息。

2赞 unutbu 10/28/2009 #3

尽量避免通过固定的数字索引访问数据,如 中所示。在一年不看你的代码之后,你(或其他人)可能需要一段时间才能弄清楚这一切在人类术语中的含义(例如,“idFoo 在表 tabelax 中的值”)。此外,如果您需要更改数据结构(例如添加另一个字段),则可能需要修复部分/全部数字索引。当破坏逻辑的风险阻止您修改数据结构时,您的代码就会僵化。fieldMap['tabelax'][0][1]

最好使用类并使用类(访问器)方法来访问数据结构。这样,即使您需要在将来的某个日期更改数据结构(在类内),也可以保留类外部的代码。

4赞 PaulMcG 10/28/2009 #4

这里有一个小的包装类,用于 FooB 模仿 FooA,但仍然保留它们的 FooB 风格。

from collections import namedtuple

# use namedtuple to define some simple classes (requires Py2.6 or later)
FooA = namedtuple('FooA', 'id name type foo')
FooB = namedtuple('FooB', 'idfoo namefoo spam')

# create a wrapper class for FooB's to look like a FooA
class FooAMimic(object):
    attrMap = dict(zip(FooA._fields, FooB._fields))
    # or if the fields aren't nicely ordered, declare this mapping explicitly
    #~ attrMap = { 'id' : 'idfoo', 'name' : 'namefoo', 'foo' : 'spam' }
    def __init__(self, obj):
        self.obj = obj
    def __getattr__(self, aname):
        ob = self.obj
        if aname in self.attrMap:
            return getattr(ob, self.attrMap[aname])
        elif  hasattr(ob, aname):
            return getattr(ob, aname)
        else:
            raise AttributeError("no such attribute " + aname)
    def __dir__(self):
        return sorted(set(dir(super(FooAMimic,self)) 
                          + dir(self.obj) 
                          + list(FooA._fields)))

像这样使用它:

# make some objects, some FooA, some FooB
fa = FooA('a', 'b', 'c','d')
fb = FooB('xx', 'yy', 'zz')
fc = FooA('e', 'f', 'g','h')

# create list of items that are FooA's, or FooA lookalikes
coll = [fa, FooAMimic(fb), fc]

# access objects like FooA's, but notice that the wrapped FooB
# attributes are still available too
for f in sorted(coll, key=lambda k : k.id):
    print f.id, '=', 
    try:
        print f.namefoo, "(really a namefoo)"
    except AttributeError:
        print f.name

指纹:

a = b
e = f
xx = yy (really a namefoo)