[Tutor] is this use or abuse of __getitem__ ?
Albert-Jan Roskam
fomcl at yahoo.com
Fri Sep 14 20:33:02 CEST 2012
> On 14/09/12 22:16, Albert-Jan Roskam wrote:
>> Hi,
>>
>> I defined a __getitem__ special method in a class that reads a binary data
>> file using a C library. The docstring should clarify the purpose of the
>> method. This works exactly as I intended it, however, the "key"
> argument is
>> actually used as an index (it also raises an IndexError when<key> is
>> greater than the number of records in the file). Am I abusing the
> __getitem__
>> method, or is this just a creative way of using it?
>
> No, that's exactly what __getitem__ is for. It does double-duty for
> key-lookup
> in mappings (dict[key]) and index-lookup in sequences (list[index]).
>
> You can also support ranges of indexes by accepting a slice argument.
COOL! I was already wondering how this could be implemented. Dive into Python is pretty exhaustive wrt special methods,
but I don't think they mentioned using the slice class. Below is how I did it. Is it recommended to define the geitem() function inside the __getitem__() method? I was thinking I could also define a _getitem() private method. Hmmm, maybe getitem() is redefined over and over again the way I did it now?
def __getitem__(self, key):
""" This function reports the record of case number <key>.
For example: firstRecord = SavReader(savFileName)[0] """
def getitem(key):
retcode1 = self.iomodule.SeekNextCase(self.fh, ctypes.c_long(int(key)))
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]" % \
(key, retcodes[retcode1], retcodes[retcode2])
return record
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
> Another comment below:
>
>
>> # Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit
> (Intel)] on win32
>>
>> def __getitem__(self, key):
>> """ This function reports the record of case
> number<key>.
>> For example: firstRecord = FileReader(fileName)[0]
> """
>> if not isinstance(key, (int, float)):
>> raise TypeError
>
> Floats? Do you actually have have case number (for example)
> 0.14285714285714285 ?
>
> For this case, I think it is reasonable to insist on exactly an int,
> and nothing else (except possibly a slice object, to support for
> example obj[2:15]).
>
I also accepted floats as a convenience. I had examples in mind like: record = data[1.0] . Kind of annoying when this raises a TypeError.
But in your example makes perfect sense to raise such an exception.
Eryksun, Steven: Thanks!!!
Albert-Jan
More information about the Tutor
mailing list