Python: неожиданное поведение при использовании contextmanager в методе класса
Я пытаюсь использовать конструкцию with..as в Python, чтобы упростить написание кода "обратимых вычислений". Однако, используя @contextmanager
на метод класса, кажется, изменить инициализацию по умолчанию будущих экземпляров класса. Python 2.6 и 3.1 ведут себя одинаково. Вот простой пример, демонстрирующий это поведение:
#!/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]
- Почему нет
SL2
свежий примерSymList
? - Как
SL2.L
элемент данных, ссылающийся наSL.L
член данных?
1 ответ
Решение
Такое поведение связано с тем, как изменяемые аргументы по умолчанию работают в Python.
Попробуйте изменить SymList.__init__()
к следующему:
def __init__(self, L=None):
if L is None:
self.L = []
else:
self.L = L
Как вы модифицируете self.L
в одном случае вы также модифицируете L
что передается в SymList.__init__()
Таким образом, в результате использования вашего кода все экземпляры будут L
атрибут при первой инициализации экземпляра.