This is a test version of Biostars. For the public version, visit https://www.biostars.org.
Creating a dictionary within a class

"Hello world",

I am using Python (2.7) and have a class that creates a string in the format of a dictionary. However, I would like to have an actual dictionary output where I can extract values by using raw_input for the keys. I have the following code so far:

class FastaFile:
    def __init__(self, path):
        self.path = path
        self._map = {}
        self.__fasta_iter()

    def __str__(self):
        return self._map.__str__()

    def __fasta_iter(self):
        fasta = open(self.path)
        fasta_iter = (x[1] for x in groupby(fasta, lambda line: line[0] == ">"))
        for header in fasta_iter:
            header = header.next()[1:9].strip()
            seq = "".join(s.strip() for s in fasta_iter.next())
            self._map[header] = seq

cff = FastaFile("obs.fasta")

I know I can use a for loop like so:

for kv in cff._map.viewitems():
    print kv

Which will give me an output like this:

('ID001','ACCGTA')
('ID002','AGTCCA')

However, I would very much like to continue with my class or perhaps create a subclass with the same output. I've been looking into it and I believe I may need __getitem__? I've tried fiddling about with my code using __getitem__ but keep getting the dreaded error messages. Any help would be much appreciated.

python dictionary class fasta getitem

cff._map is a dictionary. So print cff._map["ID001"] statement will give you 'ACGTA'. I answered your question below. Is this what you wanted?

2 answers

If you want your class FastaFile to behave like dictionary you just need to overload the builtin method __getitem__() inside your class.

def __getitem__(self, k):
    return self._map[k]

The instances of your class will then have this behaviour:

>>> cff = FastaFile("obs.fasta") 
>>> print cff['ID001']
ACCGTA

Also if you want to simplify the syntax of your iteration (for kv in cff._map.viewitems()), you can overload __iter__():

def __iter__(self):
    for k in self._map:
        yield k, self._map[k]

In this way, you can access seqid and sequence like this:

>>> for seqid, seq in cff:
..     print seqid, seq
ID001 ACCGTA
ID002 AGTCC

I wouldn't recommend storing FASTA records in dictionary unless you don't care about an order of your input sequences.

Maaaate, you are a legend! Thank you so much! Been scratching my head all day trying to add it into my class FastaFile. It works! :)

Eventually, I would like a user to input a sequence ID and the sequence associated with that ID will be the output.

Hopefully...

Maybe I don't get the problem. But....I'll try to answer:

  • you can just create that dictionary and return it to the 'outsite world' by returning it from a function. if you google "python class function" there are many examples so I don't post it here, but that would be nothing fancy
  • "I would very much like to continue with my class or perhaps create a subclass" - what do you mean with you would like to continue with your class?
  • "using __getitem__ " - you don't have to name all your function in a class with these fancy __ ..... you can just have a normal function and return a dictionary, as mentioned above.
  • Additional note: "Python (2)" - yes there is a big difference between python 2 and 3, BUT there is a huge difference between python 2.6 and 2.7 for example. So to just say 'I use python 2' does not say too much ...

Thanks for responding. I edited to Python 2.7 now. What I meant by I would like to continue with my class is because I want to use all my functions within a class (even though I know it is simpler to do otherwise sometimes).

Log in to answer this question.