On Fri, Sep 14, 2012 at 2:33 PM, Albert-Jan Roskam <fo...@yahoo.com> wrote: >> On 14/09/12 22:16, Albert-Jan Roskam wrote: > > Is it recommended to define the geitem() function inside the __getitem__() > method? > I was thinking I could also define a _getitem() private method. > > def getitem(key): > retcode1 = self.iomodule.SeekNextCase(self.fh, > ctypes.c_long(int(key))) > ....
I wouldn't do this since it incurs the cost of a repeated function call. A slice could involve thousands of such calls. Maybe use a boolean variable like "is_slice". Then use a for loop to build the records list (maybe only 1 item). If is_slice, return records, else return records[0]. > if isinstance(key, slice): > records = [getitem(i) for i in range(*key.indices(self.nCases))] > return records > elif hasattr(key, "__int__"): # isinstance(key, (int, float)): > if abs(key) > (self.nCases - 1): > raise IndexError > else: > key = self.nCases + key if key < 0 else key > record = getitem(key) > return record > else: > raise TypeError I agree with Steven's reasoning that it doesn't make sense to support floating point indexes. Python 2.6+ has the __index__ special method. int and long have this method. float, Decimal,and Fraction do not have it. It lets you support any user-defined class that can be used as an index. For example: >>> class MyInt(object): ... def __index__(self): ... return 5 >>> slice(MyInt(), MyInt(), MyInt()).indices(10) (5, 5, 5) operator.index() is the corresponding function. It raises TypeError if __index__ isn't supported. But watch out because you're using ctypes.c_long. It doesn't do any range checking. It just silently wraps around modulo the size of a long on your platform: >>> c_long(2**32-1), c_long(2**32), c_long(2**32+1) (c_long(-1), c_long(0), c_long(1)) Calling int(key) or index(key) is no help because it will silently return a Python long (big int). You need to do range checking on the upper bound and raise a ValueError. For example: from operator import index # calls obj.__index__() is_slice = isinstance(key, slice) if is_slice: start, stop, step = key.indices(self.nCases) # may raise TypeError else: start = index(self.nCases + key if key < 0 else key) # may raise TypeError stop = start + 1 step = 1 if stop > 2 ** (ctypes.sizeof(ctypes.c_long) * 8 - 1): raise ValueError('useful message') records = [] for i in range(start, stop, step): retcode1 = self.iomodule.SeekNextCase(self.fh, ctypes.c_long(i)) self.caseBuffer, self.caseBufferPtr = self.getCaseBuffer() retcode2 = self.iomodule.WholeCaseIn(self.fh, self.caseBufferPtr) record = struct.unpack(self.structFmt, self.caseBuffer.raw) if any([retcode1, retcode2]): raise RuntimeError("Error retrieving record %d [%s, %s]" % (i, retcodes[retcode1], retcodes[retcode2])) records.append(record) if not is_slice: records = records[0] return records _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor