views:

120

answers:

2

I have code for a Range class like this:

class Range:
   def __init__(self, start, end):
      self.setStart(start)
      self.setEnd(end)
   def getStart(self):
      return self.start
   def setStart(self, s):
      self.start = s
   def getEnd(self):
      return self.end
   def setEnd(self, e):
      self.end = e
   def getLength(self):
      return len(range(self.start, self.end))
   def overlaps(self, r):
      if (r.getStart() < self.getEnd() and r.getEnd() >= self.getEnd()) or \
         (self.getStart() < r.getEnd() and self.getEnd() >= r.getEnd()) or \
         (self.getStart() >= r.getStart() and self.getEnd() <= r.getEnd()) or \
         (r.getStart() >= self.getStart() and r.getEnd() <= self.getEnd()):
          return True
      else:
          return False

My assignment is to create a subclass of Range, called DNAFeature, that represents a Range that also has a strand and a sequence name:

Implement setStrand and getStrand, which set and return strand information, and setSeqName and getSeqName, which set or return the name of the sequence the feature belongs to. If a feature is on the minus (reverse) strand, getStrand() should return ‐1. If a feature is on the plus strand, getStrand() should return 1. If strand is not set, getStrand() should return 0.

I have tried to write something but doesn't look right at all for me, can everyone please help me with this, thank you so much guys, this is my code:

class DNAFeature(Range):
    def __init__(self, strand, sequence):
            self.setStrand(strand)
            self.setSeqName(sequence)
    def getSeqName(self):
            return self.plus or minus
    def setSeqName(self, seq):
            self.sequence = seq
    def getStrand(self):
            if self.getSeqName(self.strand) == 'plus':
                    return 1
            if self.getSeqName(self.strand) == 'minus':
                    return -1
            else:
                    return 0
    def setStrand(self, strand):
            self.strand = strand
+2  A: 

In general it is much easier to answer questions if you provide a specific error message or thing that is going wrong. Here's what happened when I tried to run the above:

  • First up:

    `SyntaxError: invalid syntax` 
    

    on if seq == POSITIVE. What's wrong here? Oh yes, you're missing a colon after the conditional. If you add that the file at least parses. So let's try doing some coding:

    # Your code here, then:
    feature = DNAFeature()
    
  • Running that gives:

    TypeError: __init__() takes exactly 3 positional arguments (1 given)
    

    Oh, OK, we need to pass some arguments to the initialiser of DNAFeature. Let's put this on the + strand, and call it foo:

    feature = DNAFeature(1, "foo")
    
  • Now we get:

    AttributeError: 'DNAFeature' object has no attribute 'setStrand'
    

    What's that about? OK, you haven't defined setStrand. (Note: you shouldn't have to. But more on that later.) Let's define it:

    def setStrand(self, strand):
        self.strand = strand
    

I don't want to go through the rest of the problems with the code (hint: you need to define variables before you use them), but this is the sort of thing you should be doing.


Right, something different. The above is bad code. I hope you've written the Range class and that it hasn't been provided as part of the course, because if it has you're taking a badly-taught course. The main problem is the use of getters and setters -- I'm guessing you're Java-born and bred? In Python you don't need to write getters and setters for everything, because you can always add them in later if you need them. Instead, just use class attributes. Look at the following code for Range:

class Range:
    def __init__(self, start, end):
        self.start = start
        self.end = end

    def length(self):
        return self.end - self.start

    def overlaps(self, other):
        return not(self.end < other.start or other.end < self.start)

Isn't that much nicer? No more nasty accessors, no icky comparisons in the overlaps method... It helps if you work out the logic that your code is trying to implement before you implement it.

See if you can write a better DNAFeature now.


You still haven't told me what getStrand should, do, but here's what I think you're aiming towards. Suppose the strand name that gets passed to __init__ is of the form "+name" or "-name". You can then do the following:

def __init__(self, strand):
    sequence = strand[0] #first character of strand

    if sequence == "+":
        self.strand = 1
        self.sequence= strand[1:]
    elif sequence == "-":
        self.strand = -1
        self.sequence = strand[1:]
    else:
        self.strand = 0
        self.sequence = strand

See if you can work out how that works.

katrielalex
Actually, the Range class was from a previous assignment of mine and my professor require me to input setters and getters, thats why I had it there, and I have run the Range class which worked too, in this assignemnt, my professor asks us to input that subclass for Range which is the DNAFeature to read the DNA strand feature as if its a plus or minus strand and return 1, -1, or 0 if no setting.
pmt0512
I'm sorry but about feature = DNAFeature(1, "foo")where did you put this line in, is it under the getStrand function, right before I define seq == POSITIVE?
pmt0512
@pmt: Your professor doesn't know Python. The correct idiom is to use class attributes, with data descriptors (http://docs.python.org/reference/datamodel.html#descriptors) such as `property` used when you want to perform calculations upon accessing an attribute. Getters and setters are never the right tool. I don't entirely understand your question, but I think you are asking how to set an attribute that is either -1, 0, or 1. Just set it! `self.strand = -1`, say. The line `feature = DNAFeature(1,"foo")` went at the bottom of the program.
katrielalex
@pmt: I don't mean to be disrespectful, but I think you would be better served reading a Python tutorial such as `Dive into Python` (http://diveintopython.org/toc/index.html) before writing more code; it should help you get a handle on the concepts.
katrielalex
@katrielalex: alright, as I am a beginner in programming, I dont know much what my prof do, just write whatever she ask for, and that Range class worked anyways, I dont have any clues why she put getters and setters too, but back to this assignment, what I am confusing is how to set the getSeqName and setSeqName to set and return the name for a feature sequence, which either a plus or a minus strand, then the getStrand will return 1 for plus, -1 for minus strand, and 0 for none setting strand. Can you help me with this, I really am new to programming. Thanks
pmt0512
@pmt: do you mean that the direction of the strand _depends_ on the name? If so, in what way? This goes back to something I said above: don't write the code before you know what you want it to do. `Programming is the art of figuring out what you mean so precisely that even a machine can do it.`
katrielalex
@katrielalex: basically, I know what I want to do, but I am so new to programming and don't know how to get the codes right...the feature strand, as it said will be either plus or minus strand, and the getSeqName, setSeqName will regconize it and return as plus or minus strand, then the getStrand will return 1, -1 or 0 depends on plus or minus strand, thats what I want to write, but I dont exactly know how to write the codes correctly, even I did read through books, my lectures, still, I dont have any computer background, so thats my biggest problem.
pmt0512
@pmt: you still haven't answered my question -- __what does `getSeqName` *do*__ to recognize the strand as plus or minus? If the strand is `"foo"`, is that plus or minus? How about `"flibbertigibbet"`. You need to state, in English instead of in code, what the function should do before I can help explain how to do it.
katrielalex
@katrielalex: honestly, I dont know how getSeqName recognize the strand, I have post all the instruction that my prof. gave me, but I think in the database file of DNA strand, they include the + and - sign for plus and minus strand, then getSeqName capture that +/- and return as either plus or minus.
pmt0512
@pmt: well, you can't honestly expect me to work out what your professor wants for you! However, I've updated the answer with something that may help.
katrielalex
@katrielalex: I am so sorry about that, I dont even really understand what she want either, just trying to get some help from u experts. Thank you very much for ur codes, I will try it and ask my prof again on how its gonna recognize the strand.
pmt0512
A: 

In the most generic case (without making any assumptions), it seems that this is what you need:

class DNAFeature(Range):

    def __init__(self, start, end):
        self.setStart(start)
        self.setEnd(end)
        self.strand = None
        self.sequencename = None

    def setStrand(self, s):
        self.strand = s

    def getStrand(self):
        if self.sequenceName == 'plus':
            return 1
        elif self.sequenceName == 'minus':
            return -1
        else:
            return 0

    def setSequenceName(self, s):
        self.sequencename = s

    def getSequenceName(self, s):
        return self.sequenceName

You will notice that here, I have redefined init. There is a reason for this. I remember that in one of your earlier questions, you had mentioned that this was a Java assignment, just renamed to python. In Java, constructors are not inherited (correct me if I'm wrong). Therefore, if the same grading rubric is being used, you will lose marks for not redefining the constructor here.

Hope this helps

inspectorG4dget
oh no this is totally python, not Java, maybe I made a mistake telling you it was Java last time, sorry about that, and thanks a lot for the codes, really get a hard time w/ getters and setters
pmt0512
What I mean is that your professor copied this assignment from the previous years when it was a Java assignment. I'm aware that this is a python assignment. Hence why I gave you python code
inspectorG4dget