1

I was wondering whether or not I can use a square bracket like self[avariable], so I have implemented __getitem__. The code which I have tried:

class myclass:
    def __getitem__(self,index):
        return self[index]

babe = myclass()
print babe[4]

When I run this it shows:

File "C:/Python27/df", line 3, in __getitem__
    return self[index]

recursively.

How can I use a variable like self[name] with __getitem__ in Python?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
lovemysql
  • 155
  • 1
  • 12

3 Answers3

4

Your class needs to have something to index, rather than self. For example, in this class foo, it has a member variable data which is a list. So the index operation could index out of the list data for example.

class foo():
    def __init__(self, l):
        self.data = l

    def __getitem__(self, index):
        return self.data[index]

>>> a = foo([1,2,3])
>>> a[1]
2
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • @Cybr ..is there any way that i could use something like self[avariable] ? – lovemysql Nov 14 '14 at 17:26
  • 2
    `self[avariable]` will call `self.__getitem__(avariable)`, hence the loop you get stuck in. Inside `__getitem__` you need to decide where the data should really be coming from (`self.data`, in this example). – jonrsharpe Nov 14 '14 at 17:26
  • @jonrsharpe can you give me a code which uses like self.[avariable] ??..is this possible in python ,,then please post an example as answer – lovemysql Nov 14 '14 at 17:32
  • 1
    @lovemysql You keep asking the same thing over and over. Please read the responses people are telling you. `self[variable]` does not do what you think it does, you need something to actually index out of. – Cory Kramer Nov 14 '14 at 17:34
  • @Cyber see i just want to know if using like self[avariable] in any cases is posible ?? – lovemysql Nov 14 '14 at 17:36
  • @Cyber see i just dont want to use data..without using it i want like self[avariable]..is this possible without using __getitem__ – lovemysql Nov 14 '14 at 17:37
  • @lovemysql I will say this as clearly as possible: `self[avariable]` will try to index out of `self` using the `__getitem__` method. You need to define `__getitem__` with something meaningful to index from. To restate: `self[avariable]` will call the `__getitem__` method!! – Cory Kramer Nov 14 '14 at 17:37
  • @Cyber see just leave the __getitem__ ..just consider other cases wheather i can use like self[avaribale] – lovemysql Nov 14 '14 at 17:40
  • You cannot "just leave the `getitem`"!!! That is the method that will be invoked by the `[]` operator! That is what we keep trying to tell you! – Cory Kramer Nov 14 '14 at 17:41
1

Here is a very simple class to demonstrate the theory:

class Indexable(object):

    def __getitem__(self, index):
        print("You indexed me with {}.".format(index))

In use, then:

>>> i = Indexable()
>>> i[12]
You indexed me with 12.

Here we can clearly see that i[12] resolves to Indexable.__getitem__(i, 12).

This happens everywhere - even if you call self[avariable] inside an instance method (including __getitem__), you will end up calling Indexable.__getitem__(self, avariable). This explains the infinite loop if you include self[avariable] inside Indexable.__getitem__.

This will always be the case in Python, you cannot redefine this syntax without rewriting it yourself. This is a "magic method", just like str(instance) calls Class.__str__(instance).


In practice, you will generally want to define some useful behaviour for indexing, perhaps you want to fake numpy-style comma-separated indexing:

class NotArray(object):

    def __init__(self, data):
        self.data = data

    def __getitem__(self, index):
        data = self.data
        for ind in index:
            data = data[ind]
        return data

This can be used like:

>>> arr = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
>>> arr[1, 1, 1]
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    arr[1, 1, 1]
TypeError: list indices must be integers, not tuple
>>> arr = NotArray([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
>>> arr[1, 1, 1]
8

Note that we have now defined a source for the data to be returned for a given index.


You could also use this to implement non-standard syntax, like I do in my answer to this question: is it possible to add some new syntax in javascript? But this is generally discouraged, as it will confuse readers of your code.

Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
0
class myclass(list):
    def __getitem__(self, key):
        return super(myclass, self).__getitem__(key-1)

babe = myclass()
babe.append(1)
babe.append(2)
babe.append(3)
babe.append(4)
print babe[4]
Sean Keane
  • 411
  • 1
  • 6
  • 19