Python 范围类/子类

0 投票
2 回答
3100 浏览
提问于 2025-04-16 05:20

我有一个叫做 Range 的类,代码大概是这样的:

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

我的任务是创建一个 Range 的子类,叫做 DNAFeature,这个类除了表示一个范围外,还要包含一个链(strand)和一个序列名称(sequence name):

需要实现 setStrandgetStrand 方法,用来设置和获取链的信息,还有 setSeqNamegetSeqName 方法,用来设置或获取这个特征所属的序列名称。 如果特征在负链(反向链)上,getStrand() 应该返回 -1。如果特征在正链上,getStrand() 应该返回 1。如果链没有设置,getStrand() 应该返回 0。

我尝试写了一些代码,但感觉完全不对,大家能帮帮我吗?非常感谢,以下是我的代码:

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 个回答

4

一般来说,如果你能提供具体的错误信息或者出错的地方,回答问题会简单很多。下面是我尝试运行上面的代码时发生的事情:

  • 首先:

    `SyntaxError: invalid syntax` 
    

    if seq == POSITIVE 这一行。这里有什么问题呢?哦,对了,你在条件后面缺少了一个冒号。如果你加上这个,文件至少能解析通过。那我们来试试写点代码:

    # Your code here, then:
    feature = DNAFeature()
    
  • 运行这个会得到:

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

    哦,好吧,我们需要给 DNAFeature 的初始化器传一些参数。我们把这个放在正链上,叫它 foo:

    feature = DNAFeature(1, "foo")
    
  • 现在我们得到:

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

    这又是怎么回事?好吧,你还没有定义 setStrand。 (注意:其实你不应该需要定义它。但稍后会详细说。)我们来定义一下:

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

我不想逐一讲解代码中的其他问题(提示:你需要在使用变量之前先定义它们),但这就是你应该做的事情。


好了,换个话题。上面的代码很糟糕。 我希望你已经写过 Range 类,并且它不是课程中提供的,因为如果是的话,你可能在上一个教得不好的课程。主要问题在于使用了 getter 和 setter——我猜你是从 Java 过来的?在 Python 中,你不需要为每个属性都写 getter 和 setter,因为如果需要的话,你可以随时添加它们。相反,直接使用类属性就可以了。看看下面的 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)

这样是不是好很多?不再有那些麻烦的访问器,也没有在 overlaps 方法中让人厌烦的比较……在实现代码之前,先理清楚你的代码要实现的逻辑是很有帮助的。

看看你能否写出一个更好的 DNAFeature


你还没有告诉我 getStrand 应该做什么,但我想我知道你想要的是什么。假设传递给 __init__ 的链名是 "+name""-name" 的形式。然后你可以这样做:

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

看看你能否弄明白这怎么回事。

0

在最普通的情况下(不做任何假设),看起来你需要的是这个:

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

你会注意到这里我重新定义了init。这样做是有原因的。我记得你之前提到过这是一个Java的作业,只是改成了Python。在Java中,构造函数是不会被继承的(如果我说错了请纠正我)。所以,如果使用的是相同的评分标准,你在这里不重新定义构造函数的话,会失分。

希望这对你有帮助

撰写回答