Лучший способ построить «сложную» структуру данных в Python - PullRequest
4 голосов
/ 27 октября 2009

Мне нужно создать инструмент, который будет использоваться для создания сопоставлений полей (между таблицами) максимально автоматизированным способом.

Вот сделка: представьте, что стол добавляется к другому. (давайте на секунду проигнорируем тип поля ...)

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 ]

6 голосов
/ 27 октября 2009

Честно говоря, я бы просто взял подсказки (или использовал) SQLAlchemy или Модели Django . Это проверенные и достоверные методы представления данных.

4 голосов
/ 28 октября 2009

Вот небольшой класс-обертка для 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)
2 голосов
/ 28 октября 2009

Старайтесь избегать доступа к вашим данным через фиксированные числовые индексы, как в fieldMap['tabelax'][0][1]. После года, когда вы не смотрите на ваш код, вам (или другим) может потребоваться некоторое время, чтобы понять, что все это означает в человеческом смысле (например, «значение idFoo в таблице tabelax»). Кроме того, если вам когда-либо понадобится изменить структуру данных (например, добавить другое поле), возможно, потребуется исправить некоторые / все ваши числовые индексы. Ваш код становится окостеневшим, когда риск нарушения логики мешает вам изменить структуру данных.

Гораздо лучше использовать класс и использовать методы класса (аксессора) для доступа к структуре данных. Таким образом, код вне вашего класса может быть сохранен, даже если вам нужно изменить структуру данных (внутри класса) в будущем.

2 голосов
/ 27 октября 2009

Подумайте об этом

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

Не совсем понятно, что вы пытаетесь сделать и почему, так что это так же хорошо, как и все остальное, поскольку, кажется, представляет информацию, которую вы на самом деле имеете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...