title: Should the "opening work" of a context manager happen in __init__ or __enter__?
body: <p>I found the <a href="https://book.pythontips.com/en/latest/context_managers.html" rel="nofollow noreferrer">following example</a> of a Context Manager for a <code>File</code> object:</p>
  <pre class="lang-py prettyprint-override"><code>class File(object):
      def __init__(self, file_name, method):
          self.file_obj = open(file_name, method)
      def __enter__(self):
          return self.file_obj
      def __exit__(self, type, value, traceback):
          self.file_obj.close()
  </code></pre>
  <p>Here, the <em>work</em> done by the manager, that is actually opening the file, happens in the <code>__init__</code> method. However, in the accompanying text, they suggest that the file opening should happen in the <code>__enter__</code> call:</p>
  <blockquote>
  <p>Let’s talk about what happens under-the-hood.</p>
  <ol>
  <li>The with statement stores the <strong>exit</strong> method of the File class.</li>
  <li>It calls the <strong>enter</strong> method of the File class.</li>
  <li>The <strong>enter</strong> method opens the file and returns it.</li>
  <li>The opened file handle is passed to opened_file.</li>
  <li>We write to the file using .write().</li>
  <li>The with statement calls the stored <strong>exit</strong> method.</li>
  <li>The <strong>exit</strong> method closes the file.</li>
  </ol>
  </blockquote>
  <p>Which is the correct approach in general? It seems to be that the work undone by <code>__exit__</code> should happen in <code>__enter__</code>, not <code>__init__</code> since those are paired 1:1 by the context manager mechanism, but this example leaves me doubtful.</p>