私はそのようなクラス構造を持っています:
list --(親)--> ClipList --(親)--> VolumeList
ClipList は Clip オブジェクトのみを格納でき、VolumeList は Volume オブジェクトのみを格納できます。Volume クラスは Clip クラスから継承されるため、これは機能します (つまり、ClipList から継承されたメソッドは VolumeList に対して機能します)。そこで、Volume クラスと VolumeList クラスで達成しようとしているのは、オリジナルとは十分に異なる、独自のクラスを持つことができる、Clip と ClipList のフレーバーを得ることです。
VolumeList から Volume オブジェクトを呼び出そうとすると、問題が発生します。呼び出されたクリップの場所を見つけるために、バイナリ検索を実行します (リストの順序に従って)。検索は単純な二分検索であり、文脈を無視しても機能するため、ここにコードを掲載する価値はないと思います。問題のあるビットは、次の条件です。
if ( self == [] ):
return None
現在、バイナリ検索はClipListクラスに実装されており、VolumeList によってのみ継承されます。上記の条件は、ClipList を使用する場合には問題を引き起こしませんでしたが、(既に入力された) VolumeList を使用して実行すると、条件
self == []
は、何らかの理由で、実際にはTrue
. したがって、二分検索は常に None を返し、リスト内のボリューム オブジェクトに名前 (順序付け) でアクセスすることはできません。インデックスによってのみアクセスできます。
これで、入力された 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)