2012-08-07 48 views
3

我試圖在Python中使用with..as contruct來簡化書寫「可逆計算」代碼。但是,在類方法上使用@contextmanager似乎會更改未來類實例的默認初始化。 Python 2.6和3.1具有相同的行爲。下面是一個簡單的例子出現此行爲:Python:在類方法上使用contextmanager的意外行爲

#!/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] 


  • 爲什麼不是SL2SymList一個新實例?
  • SL2.L數據成員如何引用SL.L數據成員?

回答

14

此行爲是由於mutable default arguments如何在Python中工作。

嘗試改變SymList.__init__()以下幾點:

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

在修改self.L在一個情況下,你也修改傳遞到SymList.__init__()L,使你的代碼的結果是,所有實例將共享當第一次初始化實例時,同樣的L屬性。

+0

這很有道理。我被矇蔽了,認爲這是裝飾者更有趣。謝謝! – user1582421 2012-08-07 16:14:04