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

时间:2009-10-27 17:11:09

标签: python list data-structures

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

这是交易:想象一个表被附加到其他人。 (让我们忽略字段类型,只需一秒......)

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:也许正式的结构(比如一个类)会更好?

由于

4 个答案:

答案 0 :(得分:6)

我真的只是从(或使用)SQLAlchemyDjango Models中获取提示。这些是经过验证的真实数据表示方法。

答案 1 :(得分:4)

这是FooB模仿FooA的一个小包装类,但仍然保留了他们的FooB-ishness。

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)

答案 2 :(得分: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" ) )

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

答案 3 :(得分:2)

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

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