1

I came across a piece of code today that looks like this:

class ClassName(object):
     def __init__(self):
         self._vocabulary = None

     def vocabulary(self):
         self._vocabulary = self._vocabulary or self.keys()
         return self._vocabulary

What exactly is the line self._vocabulary = self._vocabulary or self.keys() doing?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
dave
  • 12,406
  • 10
  • 42
  • 59

3 Answers3

8

A line like this:

self._vocabulary = self._vocabulary or self.keys()

Is what's called lazy initialization, when you are retrieving the value for the first time it initializes. So if it has never been initialized self._vocabulary will be None (because the __init__ method had set this value) resulting in the evaluation of the second element of the or so self.keys() will be executed, assigning the returning value to self._vocabulary, thus initializing it for future requests.

When a second time vocabulary is called self._vocabulary won't be None and it will keep that value.

Santiago Alessandri
  • 6,630
  • 30
  • 46
2

In a nutshell, if self._vocabulary evaluates to a logical false (e.g. if it's None, 0, False, etc), then it will be replaced with self.keys().

The or operator in this case, returns whichever value evaluates to a logical true.

Also, your code should look more like this:

class Example(object):
     def __init__(self):
         self._vocabulary = None

     def vocabulary(self):
         self._vocabulary = self._vocabulary or self.keys()
         return self._vocabulary

     def keys(self):
         return ['a', 'b']

ex = Example()
print ex.vocabulary()
ex._vocabulary = 'Hi there'
print ex.vocabulary()
Joe Kington
  • 275,208
  • 71
  • 604
  • 463
  • `The or operator in this case, returns whichever value evaluates to a logical true.` - This is a little misleading. If `self._vocabulary` evaluates to `False` then `self.keys()` is executed and used for the assignment, whether or not it evaluates as `True` or `False`. See http://stackoverflow.com/questions/1452489/evaluation-of-boolean-expressions-in-python/1452500#1452500 for explanation of how things evaluate in boolean expressions. – MattH May 04 '11 at 19:37
  • @dave - No, lots of other languages have similar operators. For example, the `||` operator does the same thing in ruby. The equivalent would be `vocabulary ||= keys()` or `vocabulary = (vocabulary || keys())` in ruby. It's common of plenty of other languages besides ruby and python, as well. – Joe Kington May 04 '11 at 19:39
  • @MattH - I used slightly poor phrasing, but that's _exactly_ what I was saying. I.e. logical testing, not identity testing whether it `is False`. (Thus the lowercase "logical false" and not the object `False`) Edit: whoops, I misread your comment. Good point... – Joe Kington May 04 '11 at 19:41
0

Hard to say, the code will not run for a number of reasons. To guess though, I'd say it looks like it would be evaluated as a logical expression, self._vocabulary would be evaluated False by python as type None, and self.keys() is a method that would (hopefully) return something to be evaluated as well. Then it's just a logical OR between the two and the result gets put into self._vocabulary.

Nona Urbiz
  • 4,873
  • 16
  • 57
  • 84