2009-10-27 139 views
3

我需要构建一个工具,用于以尽可能最自动的方式创建字段映射(表之间)。在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:也许一个正式的结构(像一个类)会更好吗?

感谢

+0

这不是明显的如何你的结构将用于虽然这是它的设计非常重要。另外,请使用自描述性名称,如'table_from','table_to'','id_in_table_from'来更清楚。 – 2009-10-27 17:35:17

+0

你的问题不清楚。什么是tabelax?这两张表如何关联?你想要什么连接?你的意思是一个表被附加到另一个表上? – jcdyer 2009-10-27 21:15:46

回答

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) 
5

我老老实实只取提示从(或使用)SQLAlchemyDjango Models。这些都是可靠的数据表示方法。

+0

你好,geowa!谢谢你的提示。但是我使用这个来使用ESRI的ArcObjects编写几个脚本。我不想有一个真正的大脚印工作,只是做一个简单的字段映射。不过谢谢你:D – 2009-10-27 17:20:04

+1

如果你不想在磁盘上使用实际的数据库,你可以使用SQLAlchemy和sqlite内存引擎。这里的教程可能是一个很好的起点:http://www.sqlalchemy.org/docs/05/ormtutorial.html – 2009-10-27 17:20:51

+0

@George:如果我必须做这个项目,我可能会使用基于类的方法*类似* to django – geowa4 2009-10-27 17:27:28

1

想想这

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

尽量避免通过固定的数字索引访问您的数据,如fieldMap['tabelax'][0][1]。在不查看代码一年之后,它可能会让你(或其他人)花一些时间来弄清楚它的含义(例如,“表格标签中idFoo的价值”)。另外,如果您需要更改数据结构(例如添加另一个字段),则某些/所有数字索引可能需要修复。当违反逻辑的风险阻止您修改数据结构时,您的代码就会变得僵化。

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