提问人:George Silva 提问时间:10/28/2009 更新时间:10/28/2009 访问量:6860
在 Python 中构建“复杂”数据结构的最佳方式
Best way to construct a "complex" data structure in 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]
这不是一个非常复杂的结构,但我在使用它时会遇到一些问题?有没有关于如何处理此类问题的建议?我需要(现在)至少存储 inputTable(我不想为映射的每个字段重复它)、inputField、outputField。没有理由存储 outputTable,因为这总是事先知道的。
非常感谢您的建议和过去的经验。
PS:也许正式的结构(如类)会更好?
谢谢
答:
老实说,我只是从(或使用)SQLAlchemy 或 Django 模型中获取提示。这些是久经考验的数据表示方法。
评论
想想看
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" ) )
你根本不清楚你要做什么或为什么,所以这和任何事情一样好,因为它似乎代表了你实际拥有的信息。
尽量避免通过固定的数字索引访问数据,如 中所示。在一年不看你的代码之后,你(或其他人)可能需要一段时间才能弄清楚这一切在人类术语中的含义(例如,“idFoo 在表 tabelax 中的值”)。此外,如果您需要更改数据结构(例如添加另一个字段),则可能需要修复部分/全部数字索引。当破坏逻辑的风险阻止您修改数据结构时,您的代码就会僵化。fieldMap['tabelax'][0][1]
最好使用类并使用类(访问器)方法来访问数据结构。这样,即使您需要在将来的某个日期更改数据结构(在类内),也可以保留类外部的代码。
这里有一个小的包装类,用于 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)
评论
'table_from'
'table_to'
'id_in_table_from'