2016-05-24 10 views
0

Ich habe einige Klassen, die Eigenschaften bereits definiert haben, und ich bin jetzt auf der Suche nach einer Möglichkeit, Daten in ein benanntes Tupel zu packen, um mit einer Datenbank zu interagieren. Ich möchte einige der Eigenschaften (aber nicht alle) in dem benannten Tupel haben, damit ich beim Abrufen von Daten aus der Datenbank Feldnamen zuweisen kann.Subclassing namedtuple mit Eigenschaften

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

aber print(foo._asdict()) kehrt OrderedDict([('a', 11), ('b',())]) seit dem genannten Tupel ist unveränderlich.

Die 'b' Eigenschaft kann nicht während der Instantiierung des namedtuple berechnet werden.

Kann jemand auf dem Weg in dieser Situation beraten?

+0

Warum untergliedern Sie ein 'namedtuple' dafür? – jonrsharpe

+0

Die Idee des 'namedtuple' stammt aus der Eponymdokumentation. Wenn ich vorhandene Datensätze in der Datenbank abrufe, kann ich den Feldern direkt einen Namen geben, wie er in retrieve_data angezeigt wird. Ich versuche, die gleiche zugrundeliegende Struktur zwischen einem neu erstellten Datensatz und einem vorhandenen, der aus der Datenbank abgerufen wird, zu haben. Ist es der falsche Ansatz? –

Antwort

1

Ja, das ist der falsche Ansatz. Ich weiß, dass es verlockend ist, dies zu verwenden, um wirklich kurzen Code zu haben, aber es bringt nur andere Dinge durcheinander. Halte es einfach, damit es allen Lesern (einschließlich deiner zukünftigen) offensichtlich klar wird, was vor sich geht.

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

Danke für die Bestätigung! Ich habe das Gefühl, dass die namedtuple-Struktur für einige andere Operationen auf der db nützlich sein wird. Aber als ich Ihre Antwort las, erkannte ich, dass ich, falls nötig, einfach eine 'as_namedtuple' Methode zu' FooV2' hinzufügen konnte, die eine Repräsentation des Datensatzes im gewünschten Format zurückgibt. Prost. –