2016-05-24 4 views
0

プロパティが既に定義されているクラスがいくつかあります。データベースとやりとりするために名前付きタプルにデータをパックする方法を探しています。データベースからデータを取得するときにフィールド名を割り当てることができるように、名前付きタプルにいくつかのプロパティ(ただしすべてではない)を持たせたいと思います。名前付きタプルをプロパティでサブクラス化する

from collections import namedtuple 
import sqlite3 

Foo = namedtuple('Foo', 'a, b') 

class FooChild(Foo): 

    def do_some_calculation(self): 
     self.d = 2 
     return self.d 

    @property 
    def b(self): 
     return (self.a,)*2 + (self.d,) 

    @property 
    def c(self): 
     return 'bar' 

def retrieve_data(): 
    conn = sqlite3.connect('/foodata') 
    cursor = conn.cursor() 
    cursor.execute('SELECT a, b FROM foos') 
    for foo in map(Foo._make, cursor.fetchall()): 
     print(foo.a, foo.b) 


foo = Foo(11,()) 
print(foo.a, foo.b, foo._asdict()) 

しかしprint(foo._asdict())という名前のタプルは不変であるため、OrderedDict([('a', 11), ('b',())])を返します。

namedtupleのインスタンス化中に 'b'プロパティを計算することはできません。

誰かがこのような状況に行くためにアドバイスできますか?

+0

なぜこのために名前付きタプルをサブクラス化していますか? – jonrsharpe

+0

'namedtuple'のアイデアは、eponymのドキュメントから来ました。データベース内の既存のレコードを取得するとき、現在はretrieve_dataに表示されているように、フィールドに直接名前を付けることができます。私は、新しく作成されたレコードと、dbから取得された既存のレコードとの間に同じ基本的な構造を持たせようとしています。間違ったアプローチですか? –

答えて

1

はい、これは間違ったアプローチです。私はそれが本当に短いコードを持つためにこれを使用することが魅力的だと知っていますが、それは他のものを駄目にするだけです。シンプルにしておくことで、すべての読者(未来のあなたも含めて)に何が起こっているのかはっきりと分かります。

class FooV2(object): 
    def __init__(self, a, b): 
     self.a = a 
     self.b = b 

    # c and d and stuff 

def retrieve_data(): 
    conn = sqlite3.connect('/foodata') 
    cursor = conn.cursor() 
    cursor.execute('SELECT a, b FROM foos') 
    for row in cursor.fetchall(): 
     foo = FooV2(*row) 
     print(foo.a, foo.b) 
+0

ご確認いただきありがとうございます! namedtuple構造体がdb上の他の操作のために便利であると感じています。しかし、あなたの答えを読んで、必要ならば、 'as_namedtuple'メソッドを' FooV2'に追加するだけで、目的のフォーマットでレコードの表現を返すことができました。乾杯。 –

関連する問題