我有这样一个类结构:
list --(parent)--> ClipList --(parent)--> VolumeList
ClipList 只能存储 Clip 对象,而 VolumeList - 只能存储 Volume 对象。这有效(即从 ClipList 继承的方法适用于 VolumeList),因为 Volume 类继承自 Clip 类。因此,我尝试使用 Volume 和 VolumeList 类实现的目的是让 Clip 和 ClipList 的风格与原来的不同,从而拥有自己的类。
当我尝试从 VolumeList 调用 Volume 对象时,就会出现问题。为了找到一个被调用的剪辑的位置,我运行了一个二分搜索(因为列表是有序的)。搜索是一个简单的二进制搜索,并且脱离了上下文可以工作,所以我认为不值得在这里发布代码。有问题的一点是这个条件:
if ( self == [] ):
return None
现在,二分查找是在ClipList类中实现的,并且仅由 VolumeList 继承。上述条件在使用 ClipList 时没有引起任何问题,但是当使用(已填充的)VolumeList 运行时,条件
self == []
是,由于某种原因,实际上True
。因此,二分查找总是返回 None,并且我无法通过名称(它们的排序)访问列表中的任何 Volume 对象,它们只能通过索引访问。
现在,填充的 VolumeList 看起来像这样(虽然大得多):
[<__main__.Volume instance at 0xb6f3b1ac>, <__main__.Volume instance at 0xb6f3b24c>]
另外值得一提的是 ClipList 与 VolumeList 位于不同的模块中 - 这可能有作用,但我不确定。
如果需要,我可以发布更多代码,但我觉得问题(和解决方案)在于上面的位;如果与上述位分开测试,其他代码似乎可以工作。
问题可能出在哪里,为什么会出现这种情况True
?
这是代码:
ClipList.findIndex
:def findIndex(self, clip, start = 0, end = None, pos = 0): # Finds the index of the place where the given clip should be added. # It does that by looking at the *tapes* of the clips, and finds # a place where the *tape* of the clip could be inserted without # distorting the order. It then looks at clip's timecode to put it # in the right place according to the timecode. The 'pos' parameter # carries the information about the index which we will return. # Define the right end place if none is specified if ( end == None ): end = len(self) - 1 # But first of all, check if there is a need to find the place of the # clip - i. e. if the list isn't empty. if ( not self ): return None # The second check that we have to make - whether it isn't the case # that we have already found what we need, i. e. the closest element # in the list to the clip we search. if ( start > end ): return pos # Now, we can implement the actual search. To do that, # we use the binary search algorithm. middle = (start + end) / 2 currTape = Clip.physicalTape( self[middle].VOLUME ) goalTape = Clip.physicalTape( clip.VOLUME ) if ( currTape > goalTape ): return self.findIndex(clip, start, middle -1, middle ) if ( currTape < goalTape ): return self.findIndex(clip, middle + 1, end, middle + 1) if ( currTape == goalTape ): currTimecode = self[middle].IN goalTimecode = clip.IN if ( currTimecode > goalTimecode ): return self.findIndex(clip, start, middle - 1, middle ) if ( currTimecode < goalTimecode ): return self.findIndex(clip, middle + 1, end, middle + 1)
VolumeList.__getitem__
:def __getitem__(self, key): # Is called whenever someone tries to get an item of the list # by calling 'volumes[ some_text_or_number ]'. VolumeList # will act as a normal list in all occassions except where the # key is a string. There, it will search for a volume label or # a tape number. if ( isinstance( key, basestring ) ): # Before checking whether the argument is a volume # number, try to find if the user hasn't made an inquiry # about a tape. Tapes can only be called by calls such as # 'volumes[ "HD00345" ]', and *not* any other calls. if ( len(key) == 7 and key[:2].upper() == 'HD' and key[2:].isdigit() ): # Try to find the start and end of the sequence of # volumes from the tape. To do this, search for an # 'infinitely small' and 'infinitely big' volumes from # the tape. start = self.findIndex( Volume( key.upper() + 'A', inFrame = -1 ) ) end = self.findIndex( Volume( key.upper() + 'Z', inFrame = 9999999 ) ) if ( start != None and end != None ): return self[start:end] else: raise KeyError( 'The tape is not represented in this VolumeList!' ) # Otherwise, assume that the user has called a particular # volume. volume = Volume.volumeLabel( key ) if ( volume != None ): index = self.findIndex( Volume( volume, inFrame = -1 ) ) if ( index < len( self ) and index != None ): if ( self[ index ].LABEL == volume ): return list.__getitem__(self, index) else: print 'The volume is here but not exactly' raise KeyError( 'The volume is not in the list!' ) else: raise KeyError( 'The volume is not in the list!' ) else: raise KeyError( 'Tried to call a volume by an invalid volume label!' ) else: return list.__getitem__(self, key)