在Python中构建“复杂”数据结构的最佳方式
我需要制作一个工具,用来尽可能自动化地创建字段映射(在表之间)。
这里的情况是:想象一下一个表要添加到另一个表中。(暂时不考虑字段类型……)
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]
这个结构并不复杂,但在使用时可能会遇到一些问题?有没有什么建议可以帮助我处理这类问题?我现在需要存储至少输入表(我不想为每个映射的字段重复它)、输入字段和输出字段。输出表没有必要存储,因为它总是事先已知的。
非常感谢大家的建议和经验分享。
PS:也许使用一个正式的结构(比如类)会更好?
谢谢
4 个回答
2
尽量避免通过固定的数字索引来访问你的数据,比如用 fieldMap['tabelax'][0][1]
这种方式。因为如果你一年后再看你的代码,可能需要花一些时间才能搞清楚这些数字代表的具体意思(比如“tabelax表中idFoo的值”)。而且,如果你需要更改数据结构(比如添加一个字段),那么你之前用的数字索引可能就得修改。这样一来,你的代码就变得很僵化,因为担心修改逻辑会出错而不敢去改动数据结构。
使用类来管理数据会好很多,利用类的方法来访问数据结构。这样,即使将来你需要更改类内部的数据结构,外部的代码也能保持不变。
6
老实说,我建议你可以参考一下SQLAlchemy或者Django模型。这两种方法都是经过验证的数据表示方式,非常可靠。
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)