2009-10-27 108 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的價值」)。另外,如果您需要更改數據結構(例如添加另一個字段),則某些/所有數字索引可能需要修復。當違反邏輯的風險阻止您修改數據結構時,您的代碼就會變得僵化。

使用類並使用類(訪問器)方法訪問數據結構要好得多。這樣,即使您需要在將來的某個日期更改您的數據結構(類內部),您類之外的代碼也可以保留。