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 атрибут при первой инициализации экземпляра.

Другие вопросы по тегам