6

I've come across some code where square brackets are used on "self". I'm not familiar with this notation and as I'm trying to get my head around source code not written by me, it makes it difficult to understand what sort of object is being dealt with here.

The example I've come across is in the Natural Language Toolkit for Python here. You can find an example of what I mean if you ctrl-F self[context].

It may not be possible to tell exactly how it's being used without more context, but here's a snippet with an example:

context = tuple(context)
if (context + (word,) in self._ngrams) or (self._n == 1):
     return self[context].prob(word)
else:
     return self._alpha(context) * self._backoff.prob(word, context[1:])
user1002973
  • 2,088
  • 6
  • 22
  • 31
  • 4
    Might I suggest you [**read this page**](http://docs.python.org/2/reference/datamodel.html) in its entirety? Yes, from *top to bottom*. – phant0m Dec 17 '12 at 22:02
  • 4
    @phant0m -- That's good advice. I feel like *I* should even do it. (I'm pretty sure I've read the whole thing, but never all in 1 go). – mgilson Dec 17 '12 at 22:05
  • @mgilson The sad thing is, I don't think I've ever seen a question referencing that page. So I still don't know whether people don't understand it, or don't read it. – phant0m Dec 17 '12 at 22:13
  • 1
    Some people just stop reading after 140 characters :) – John La Rooy Dec 17 '12 at 22:14
  • @gnibbler The same that write 140-line functions? – phant0m Dec 17 '12 at 22:15

3 Answers3

7

square brackets are python's way of saying "call the __getitem__ (or __setitem__) method."

x = a[...]  #call a.__getitem__(...)
a[...] = x  #call a.__setitem__(...)
del a[...]  #call a.__delitem__(...)

In your case, there's nothing different between self and a. In fact, there's nothing special about self in a class's method at all. The first argument passed to a method is an instance of the class, but you can call that argument anything you want. self is just a (very highly recommended) convention.

mgilson
  • 300,191
  • 65
  • 633
  • 696
3

self is just an identifier, so this is the same as doing [] on any other object. For this to work, self has to implement __getitem__, the "magic method" that is invoked by the square brackets.

E.g.

class OneItemContainer(object):
    def __init__(self, value):
        self.value = value

    def __getitem__(self, i):
        if i != 0:
            raise IndexError("this container can only hold one object")
        return self.value

Now you can do

container = OneItemContainer("ham")
print(container[0])  # will print ham

But there's no reason why you shouldn't be able use [] from within a method:

    # on the previous class
    def __repr__(self):
        return "OneItemContainer(%r)" % self[0]
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
1

this

def __getitem__(self, item):
    return self._model[tuple(item)]

allows iterating the data owned by the object.

object.__getitem__(self, key)
Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

http://www.python.org/dev/peps/pep-0234/

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178