2017-02-08 1 views
2

Gibt es eine Möglichkeit, einem Wörterbuch einen speziellen Schlüssel zuzuweisen, der tatsächlich nichts tut?Gibt es einen speziellen Wert, der keinen Schlüssel in ein Wörterbuch einfügt

Ich möchte wie etwas tun:

mydict = {} 
key, value = 'foo', 'bar' 
mydict[key] = value % now my dict has {'foo': 'bar'} 

hier einige „special“ Ich möchte Wert von Schlüssel nun so, dass wenn ich laufe:

mydict[key] = value 

Es eigentlich nichts tun, so ist myDict noch { 'foo': 'bar'} (keine zusätzlichen Schlüssel oder Werte hinzugefügt)

ich versucht, mit:

d[None] = None # It actually adds {None: None} to the dict 
d[] = []   # Invalid syntax 

Warum brauche ich diese:

Nun, es ist im Grunde einen anfänglichen Fall zu behandeln.

ich eine Datei haben, die eigentlich ein FASTA-Format ist:

>id_3362 
TGTCAGTGTTCCCCGTGGCCCTGCGGTTGGAATTGCAGCGGGTCGCTTTAGTTCTGGCAT 
ATATTTTGACGGTGCCGGCCGGCGATACTGACGTGTGAGGACTTGAATTTGTACCAGCGC 
AACACTTCCAAAGCCTGGACTAGGTTGT 
>id_4743 
CGGGGGATCTAATGTGGCTGCCACGGGTTGAAAAATGG 
>id_5443 
ATATTTTGACGGTGCCGGCCGGCGATACTGACGTGTGAGGACTTGAATTTGTACCAGCGC 
AACACTTCCAAAGCCTGGACTAGGTTGT 

Mein Ansatz ist Zeile für Zeile zu lesen, die Linien in eine Folge verketten, bis der nächste Schlüssel gefunden wird (Linie beginnend mit>). Dann speichere ich den Schlüssel (id) mit dem zugehörigen Wert (Sequenz) in einem Wörterbuch, aktualisiere den Schlüssel und beginne die nächste Sequenz zu akkumulieren.

Natürlich kann ich einen dedizierten Code (wiederholt) haben, der den ersten Fall behandelt (was ich denke, es ist kein sauberer Ansatz) oder ich kann einen if innerhalb der Schleife haben, die jede Zeile liest (was jedes Mal ausgeführt wird)

Also der sauberste Ansatz wäre jedes Mal, wenn eine ID gefunden wird, speichern Sie die vorherige ID mit dem aufgelaufenen Seq zum Dictionay, aber um die erste Zeile zu behandeln, brauche ich einen speziellen Wert für den Schlüssel.

Hier ist mein Code:

def read_fasta(filename): 
    mydict = {} 
    id = None  # this has to be the special character I'm looking for 
    seq = '' 

    with open(filename) as f:    
     for line in f: 
      if line[0] == '>': 
       mydict[id] = seq    # save current id and seq 
       id = line[1:].rstrip('\n') # update id 
       seq = ''      # clean seq 
      else: 
       seq += line.rstrip('\n')  # accumulate seq 

Wie Sie in diesem Code der ersten Zeile sehen den Wert {None: ''} einfügen in das Wörterbuch.

Ich könnte natürlich diesen Schlüssel am Ende löschen, aber ich frage mich, ob ich einen Anfangswert haben kann, der nichts bei der Ausführung einfügt.

Irgendwelche Vorschläge?

+3

, was ist der Sinn? Warum nicht: nicht an erster Stelle: 'if id ist nicht None: mydict [id] = seq' –

+0

Es ist eigentlich eine Option, aber es bedeutet das Einfügen von etwas nutzlos Zeug, das später entfernt werden muss. Ich frage mich nur, ob es einen "sauberen" Weg gibt, dies zu tun. –

+0

Da das vorgeschlagene 'if' immer ausgeführt wird, wenn eine Zeile mit einem Schlüssel gefunden wird. In einer Datei mit Millionen von Schlüsseln werden Sie die Bedingung jedes Mal ausführen, nur um einen Anfangsfall zu behandeln. –

Antwort

3

Natürlich könnten Sie tun:

id = None 

dann:

if id is not None: mydict[id] = seq 

Wenn Sie Einfügen ohne if Versuche vermeiden möchten, können Sie auch einen nicht-hashable Wert beim Start nutzen könnten.

id = [] 

dann fangen Sie die "nicht hashbare Ausnahme". Das würde funktionieren, obwohl hässlich, aber ohne zusätzlichen Aufwand, da die Ausnahme nur einmal ausgelöst wird.

try: 
     mydict[id] = seq 
    except TypeError: 
     pass 

Abgesehen: Wenn Geschwindigkeit Ihre Sorge ist, dann String-Verkettung nicht

verwenden
seq += line.rstrip('\n') 

nur schrecklich underperformant ist. Statt dessen:

  • definieren seq als list: seq = []
  • append Zeilen seq: seq.append(line.rstrip('\n'))
  • am Ende schaffen die endgültige string: seq = "".join(seq)
Verwandte Themen