2017-02-15 23 views
2

所以我有這樣的代碼:Python類無意單

# The Headers class is like a dictionary but is able to store multiple name-value pairs with the same name 
class Headers: 
    def __init__(self, index = []): 
     self.index = index 

    def __contains__(self, name): 
     for own_name, value in self.index: 
      if name.lower() == own_name.lower(): 
       return True 
     return False 

    def __getitem__(self, name): 
     for i in range(len(self.index)): 
      if name.lower() == self.index[i][0].lower(): 
       return self.index[i][1] 

    def __iter__(self): 
     return HeadersIterator(self) 

    def __setitem__(self, name, value): 
     for i in range(len(self.index)): 
      if name.lower() == self.index[i][0].lower(): 
       self.index[i][1] = value 

    def add(self, name, value): 
     self.index.append((name, value)) 

class HeadersIterator: 
    def __init__(self, headers, index = 0): 
     self.headers = headers 
     self.index = index 

    def __next__(self): 
     if self.index >= len(self.headers.index): 
      raise StopIteration() 

     result = self.headers.index[ self.index ] 
     self.index += 1 

     return result 

我只是有這個問題吧,當我嘗試使用它,它似乎表現得好像它放在一個單例。下面是一些其他代碼,顯示我使用它:

def headers(self): 
     hs = Headers() 
     print("huh?", Headers, hs.index,) 

     # Most headers start with HTTP_ 
     for name, value in self.environ.items(): 
      if name.startswith('HTTP_'): 
       parts = [ (x[0].upper() + x[1:].lower()) for x in name[ len('HTTP_') : ].split('_') ] 

       hs.add('-'.join(parts), value) 

     # Some don't 
     if 'CONTENT_LENGTH' in self.environ: 
      hs.add('Content-Length', str(self.environ['CONTENT_LENGTH'])) 

     return hs 

現在看來,它第二次打印「嗯?」行,看起來hs變量指向相同的Headers對象,這意味着它只會繼續添加到它返回的相同Headers變量,下一次有更多的條目。 任何幫助,非常感謝!

+0

不,列表總是相同的。 –

+0

可能與此有關:'index = []):'。我知道使用默認列表會導致問題,因爲它們是可變的。 – Carcigenicate

+0

@JacquesdeHooge:我不確定這會解決任何問題,因爲在這種情況下** [] [:]'的**參考將被複制** ... –

回答

2

Header本身不是單,但他們把自己所有的相同index。這是由於構造:

def __init__(self, index= []): 
    # ...

這意味着Python的構造一個列表併爲每個構造函數調用沒有給index,以引用相同的列表給出。

你可以通過解決它的不可變的(例如None),然後使用if聲明,構建像一個新的列表:

def __init__(self, index= None): 
    if index is None: 
     index = [] 
    # ...

雖然有一定的場景它是通過一個全球性的有用參考構造函數(就像你在這裏做的那樣),建議儘可能使用可變對象作爲默認值:總是考慮傳遞不可變項(如42,None,'foobar',True,(),...)。

+1

啊謝謝,我已經注意到有人在玩,當我刪除默認參數時,問題消失了。現在我知道爲什麼。謝謝。 –