Python 范围类/子类
我有一个叫做 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):
需要实现 setStrand
和 getStrand
方法,用来设置和获取链的信息,还有 setSeqName
和 getSeqName
方法,用来设置或获取这个特征所属的序列名称。
如果特征在负链(反向链)上,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 个回答
一般来说,如果你能提供具体的错误信息或者出错的地方,回答问题会简单很多。下面是我尝试运行上面的代码时发生的事情:
首先:
`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
看看你能否弄明白这怎么回事。
在最普通的情况下(不做任何假设),看起来你需要的是这个:
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中,构造函数是不会被继承的(如果我说错了请纠正我)。所以,如果使用的是相同的评分标准,你在这里不重新定义构造函数的话,会失分。
希望这对你有帮助