title: What can go wrong if operators have side-effects?
body: <p>I came across a Python library that defines a class analogous to the following, where the <code>&gt;&gt;</code> operator is overloaded to have a global side-effect: </p>
  
  <pre><code>from collections import defaultdict
  
  class V(object):
      """A Vertex in a graph."""
  
      graph = defaultdict(list)  # accessed globally
  
      def __init__(self, label):
          self.label = label
  
      def __rshift__(self, other):
          V.graph[self].append(other)
          return other
  
      def __repr__(self):
          return 'V(%r)' % (self.label,)
  </code></pre>
  
  <p>The library does this because "it gives the user some nice syntax" for symbolically building up networks, by writing down simple expressions such as:</p>
  
  <pre><code>a = V('a')
  b = V('b')
  c = V('c')
  a &gt;&gt; b &gt;&gt; c &gt;&gt; c
  </code></pre>
  
  <p>in order to build a network where <code>a</code> is connected to <code>b</code>, which is connected to <code>c</code>, which is recurrently connected to itself.</p>
  
  <p>There is similar machinery within the <code>+</code>, <code>*</code>, and <code>@</code> operators as well. All of this behaviour is documented and to be expected by the user.</p>
  
  <p>However, are there any strange things that could happen, where you wouldn't think the expression should be evaluated—but actually is—or vice-versa? That is, does the execution model for Python ever assume that certain expressions are free from any side-effects? I want to know if there is any precedent, or whether any special precautions need to be taken by the user.</p>