Python编程帮助

4 投票
3 回答
1922 浏览
提问于 2025-04-16 06:32

我正在处理一个Python文件:

class Range:
    """ An object that has a non-negative start position and a non-negative length"""
    def __init__(self, start, end):
                """
                Function: generates a new Range
                Returns : a new range
                Args    : start - start position
                          end - end position
                Start and End must be non-negative """
                self.start = 0
                self.end = 10000
        self.setStart(start)
        self.setEnd(end)
    def getStart(self):
                """
                Function: get the start of the range
                Returns : a number or None
                Args    : start - the int index of the first nucleotide of this range """
        return self.start
    def setStart(self, s):
                """
                Function: set the start of the range
                Returns : None
                Args    : start - a non-negative int or None """
                if type(s) !=int:
                        raise TypeError ("Cannot set Start as this is not an interger")
                elif s < 0:
                        raise ValueError ("Cannot set Start as this is not a non-negative int")
                elif s > self.end:
                        raise ValueError("start cannot be larger than end")
                else:
                        self.start = s
    def getEnd(self):
                """
                Function: get the end of the range
                Returns : a number
                Args    : 
                """
        return self.end
    def setEnd(self, e):
                """
                Function: set the end of the range
                Returns : None
                Args    : end - a non-negative int or None
                """
                if type(e) !=int:
                        raise TypeError ("Cannot set End as this is not an interger")
                elif e < 0:
                        raise ValueError ("Cannot set End as this is not a non-negative int")
                elif e < self.start:
                        raise ValueError ("end has to be larger than start")
                else:
                        self.end = e
    def getLength(self):
                """
                Function: get the length of the range
                Returns : an int. the length of this range
                Args:
                """
                return self.end - self.start
    def overlaps(self, r):
                """
                Function: to test if two nucleotide is overlap
                Returns : True or False
                Args    : other - a Range object
                """
                start1 = self.getStart()
                end1 = start1 + self.getLength()
                start2 = r.getStart()
                end2 = start2 + self.getLength()
                max_start = max(start1,start2)
                min_end = min(end1,end2)
                return min_end - max_start > 0
        if self.getStart() == r.getStart():
                        return True
        else:
            return False

class DNAFeature(Range):
        """Represents a feature on a DNA sequence """
        def __init__(self, seq_name = None, strand = 0, **kwargs):
                """
                Function : represents a rane
                Returns  :
                Args     : strand, seqname, **kwargs
                """         
                Range.__init__(self, **kwargs)
                self.setStrand(strand)
                self.setSeqName(seq_name)
        def getSeqName(self):
                """
                Function: Gets object's Sequence Name
                Returns : seqname - string
                Args    : 
                """
                return self.seq_name
        def setSeqName(self, seq_name):
                """
                Function: Sets object's Sequence Name
                Returns : None
                Args    : seqname - mRNA accession name
                """
        self.seq_name = seq_name
        def getStrand(self):
                """
                Function: Retrieve the strand affiliation of this
                Returns : 1, 0, -1 - strand
                Args    : 
                """
                return self.strand
        def setStrand(self, strand):
                """
                Function: sets which strand the object is on
                Returns : None
                Args    : strand - one of ['+',1,'F','-',-1,'R']
                """
                StrandValues = [1, 0, -1]

        if not strand in StrandValues:
            raise ValueError("only able to setStrand if the values is 1, 0, or -1")
        else:
                        self.strand = strand
        def overlaps(self, other, ignore_strand = True): 
                """
                Function: tests if this overlaps other
                Returns : true if the ranges have same Seqname and overlap, false if not
                Args    : other - another Range object
                """
                if ignore_strand == True and self.getSeqName() == other.getSeqName():
                    return Range.overlaps(self,other)
                else:
                    return False

class GeneModel(DNAFeature):
        def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs):
               """
               Function : contains a group of DNAFeature objects representing exons
               Returns  :
               Args     : **kwargs
               """
               DNAFeature.__init__(self, **kwargs)
               self.setTranslStart(transl_start)
               self.setTranslStop(transl_stop)
               self.setDisplayId(display_id)
               self.exons = [ ]
        def getFeats(self):
                """
                Function: gets object's feats list
                Returns : list of feature keys
                Args    : feature_type - the type of strand the object holds
                """
                self.exons.sort(cmp=self.start)
                return self.exons
        def addFeat(self, feat):
                """
                Function: adds SeqFeature to feats keys
                Returns : None
                Args    : feat - a single SeqFeature object
                """
                if type(feat) == DNAFeature:
                        self.exons.append(feat)
                else:
                        raise TypeError("Cannot add feature as it is not a type of DNAFeature")
        def setTranslStart(self, transl_start):
               """
               Function : accepts an non-negative int, sets the start position of the initiating ATG
               Returns  :
               Args     : transl_start
               """
               if transl_start == None:
                   self.transl_start = None
                   return
               elif type(transl_start) !=int:
                   raise TypeError("TranslStart cannot be set since it is not a type of int")
               elif transl_start < 0:
                   raise ValueError("TranslStart cannot be set to a negative int")
               else:
                   self.translStart = transl_start
        def getTranslStart(self):
                """
                Function: the start position of initiating ATG codon
                Return  : an int.
                Args    :
                """
                return self.transl_start
        def setTranslStop(self, transl_stop):
                """
                Function: set the end position of initiating ATG codon
                Return : None
                Args   : a positive int
                """
                if transl_stop == None:
                   self.transl_stop = None
                   return
                elif type(transl_stop) !=int:
                   raise TypeError("TranslStop cannot be set since it is not a type of int")
                elif transl_stop < 0:
                   raise ValueError("TranslStop cannot be set to a negative int")
                else:
                   self.translStop = transl_stop
        def getTranslStop(self):
                """
                Function: the end position of initiating ATG codon
                Return  : an int.
                Args    :
                """
                return self.transl_stop
        def setDisplayId(self, display_id):
                """
                Function: set the display id
                Returns : None
                Args    : display_id - a string, a preferred name for this
                """
                if type(display_id) !=str:
                        raise TypeError("Cannot set displayId as it is not a type string")
                else:
                        self.display_id = display_id
        def getDisplayId(self):
                """
                Function: get the display id
                Returns : display_id - a string, a preferred name for this, e.g AT1G10555.1
                Args    : 
                """
                return self.display_id

然后,我从教授那里拿到了一些代码来测试我的文件:

class TestGeneModelConstructor(unittest.TestCase):
    def testGeneModelConstructor(self):
        """GeneModel constructor supports named arguments display_id,transl_start,transl_stop"""
        p1.GeneModel(start=0,end=10,seq_name='something',strand=1,display_id='foobar',
                     transl_start=0,transl_stop=10)

    def testGeneModelConstructorDefaults(self):
        """Default values for display_id, transl_start, transl_stop should be None"""
        r = p1.GeneModel()
        self.assertEquals(r.getDisplayId(),None)
        self.assertEquals(r.getTranslStart(),None)
        self.assertEquals(r.getTranslStop(),None)

    def testGeneModelConstructorWrongTypeDisplayId(self):
        """Raise a TypeError if display_id is not a string."""
        self.assertRaises(TypeError,p1.GeneModel,display_id=0)

    def testGeneModelConstructorWrongTypeTranslStart(self):
        """Raise a TypeError if transl_start is not an int."""
        self.assertRaises(TypeError,p1.GeneModel,transl_start='0')

    def testGeneModelConstructorWrongTypeTranslStop(self):
        """Raise a TypeError if transl_stop is not an int."""
        self.assertRaises(TypeError,p1.GeneModel,transl_stop='0')

    def testGeneModelConstructorWrongValueTranslStart(self):
        """Raise a ValueError if transl_start is int < 0."""
        self.assertRaises(ValueError,p1.GeneModel,transl_start=-1)

    def testGeneModelConstructorWrongValueTranslStop(self):
        """Raise a ValueError if transl_stop is int < 0."""
        self.assertRaises(ValueError,p1.GeneModel,transl_stop=-1)

我运行了它,但出现了这些错误:

ERROR: Default values for display_id, transl_start, transl_stop should be None
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 117, in testGeneModelConstructorDefaults
    r = p1.GeneModel()
TypeError: __init__() takes at least 3 arguments (1 given)

======================================================================
ERROR: Raise a ValueError if transl_start is int < 0.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 136, in testGeneModelConstructorWrongValueTranslStart
    self.assertRaises(ValueError,p1.GeneModel,transl_start=-1)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 336, in failUnlessRaises
TypeError: __init__() takes at least 3 non-keyword arguments (2 given)

======================================================================
ERROR: Raise a ValueError if transl_stop is int < 0.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 140, in testGeneModelConstructorWrongValueTranslStop
    self.assertRaises(ValueError,p1.GeneModel,transl_stop=-1)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/unittest.py", line 336, in failUnlessRaises
TypeError: __init__() takes at least 3 non-keyword arguments (1 given)

我不太确定哪里出了问题,我尝试修复了几次,但还是没搞明白我的代码哪里有问题。

好吧,我在DNAFeature里把我的代码改成了这样:

class DNAFeature(Range):
    """Represents a feature on a DNA sequence """
    def __init__(self, seq_name = None, strand = 0, **kwargs):
            """
            Function : represents a rane
            Returns  :
            Args     : strand, seqname, **kwargs
            """         
            Range.__init__(self, 0,10000, **kwargs)
            self.setStrand(strand)
            self.setSeqName(seq_name)

然后,又出现了3个错误和1个失败,像这样:

ERROR: DNAFeature on different sequence don't overlap
----------------------------------------------------------------------
  Traceback (most recent call last):
     File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 164, in testDiffSequenceOverlaps
    r1 = p1.DNAFeature(start=0,end=10,strand=1,seq_name="foo")
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

======================================================================
 ERROR: DNAFeatures on the same strand can overlap if ignore_strand is True.
----------------------------------------------------------------------
  Traceback (most recent call last):
     File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 185, in testDiffStrandsDontOverlap
    r1 = p1.DNAFeature(start=0,end=10,strand=1,seq_name="foo")
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

======================================================================
ERROR: GeneModel constructor supports named arguments display_id,transl_start,transl_stop
----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 113, in testGeneModelConstructor
    transl_start=0,transl_stop=10)
     File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 151, in __init__
    DNAFeature.__init__(self, **kwargs)
      File "/Users/trungpham/binf_prog/tpham22/project1/p1.py", line 95, in __init__
    Range.__init__(self, 0, 10000, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'start'

FAIL: Raise a TypeError if seq_name is not a string.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/trungpham/binf_prog/class/test/testProject1.py", line 98, in testDNAFeatureSeqNameConstructorWrongType
    self.assertRaises(TypeError,p1.DNAFeature,seq_name=0)
AssertionError: TypeError not raised

3 个回答

1

看起来这些测试是默认所有参数都是按值传递的。你需要给位置参数设置默认值。

1

Smashery说得对。试试运行这段简化的代码:

class GeneModel(object):
    def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs):
        pass

def testGeneModelConstructor():
    g = GeneModel(start=0,end=10,seq_name='something',strand=1,display_id='foobar', transl_start=0,transl_stop=10)

def testGeneModelConstructorDefaults():
    r = GeneModel()

testGeneModelConstructor()
testGeneModelConstructorDefaults()
2

这里有几个问题:

首先:

在你的测试函数 testGeneModelConstructorDefaults 中,你写了注释:“display_id、transl_start 和 transl_stop 的默认值应该是 None”。

你遇到的问题是,你只为三个参数中的一个设置了默认值;而这个测试函数假设你已经为所有三个参数都设置了默认值。要解决这个问题,你需要这样定义构造函数:

def __init__(self, transl_start=None, transl_stop=None, display_id = None, **kwargs)

通过使用关键字参数,它会默认使用 None。如果你没有明确指定这些关键字参数,Python 就会报错(就像现在这样)。

其次:

你还得考虑你的父类构造函数。Range 这个父类需要两个参数:start 和 end。

def __init__(self, start, end):

但是,当 DNAFeature 的构造函数调用 Range 父类时,并没有传入 begin 或 end:

Range.__init__(self, **kwargs)

我认为 现在的错误就在这里(我觉得之前是在 p1.GeneModel() 的调用那里 - 你两个错误信息中可能有不同的错误行)。

要解决这个问题,也要把 start 和 end 的值变成关键字参数。所以,不要这样写:

def __init__(self, start, end):

而是要这样写:

def __init__(self, start=0, end=10000):

然后你可以删除你 range 构造函数中的以下几行代码:

self.start = 0
self.end = 10000

这样至少可以让你解决这个错误 - 你可能还会发现其他错误。

撰写回答