5

I'm trying to use the with..as contruct in Python to make writing "reversible computing" code easier. However, using @contextmanager on a class method seems to change the default initialization of future class instances. Python 2.6 and 3.1 have the same behavior. Here is a simple example exhibiting this behavior:

#!/usr/bin/env python

import contextlib

class SymList:
    def __init__(self, L=[]):
        self.L = L

    @contextlib.contextmanager
    def SymAdd(self, a):
        self.L.append(a)
        yield
        self.L.append(a)

SL = SymList()
with SL.SymAdd(3):
    SL.L.append(5)
print(SL.L) # Expect and see [3, 5, 3]
SL2 = SymList()
print(SL2.L) # Expect [] and see [3, 5, 3]


  • Why isn't SL2 a fresh instance of SymList?
  • How is the SL2.L data member referring to the SL.L data member?
0

1 Answer 1

15

This behavior is due to how mutable default arguments work in Python.

Try changing SymList.__init__() to the following:

    def __init__(self, L=None):
        if L is None:
             self.L = []
        else:
             self.L = L

As you modify self.L in one instance you are also modifying the L that is passed into SymList.__init__(), so the result with your code is that all instances would share the same L attribute when the instance is first initialized.

Sign up to request clarification or add additional context in comments.

1 Comment

That makes sense. I was blinded thinking it was something fancier with decorators. Thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.