简体   繁体   中英

Python dictionary class, 'KeyError'

I have the following class which I use to store settings for other objects to access:

#!/usr/bin/env python                                                           

class Settings:                                                                    
    """Singleton settings class"""                                              

    settings = {                                                                   
                   'SectionA': {'a': 1, 'b': 2, 'c': 3},                           
                   'SectionB': {'d': 4, 'e': 5, 'f': 6}                            
               }                                                                   

    def __getitem__(self, key): return self.settings[key]                          
    def __setitem__(self, key, item): self.settings[key] = item                    
    def keys(self): return self.settings.keys()                                    

s = Settings()                                                                     
print s.keys()                                                                     
print s['SectionA']                                                                
print s['SectionB']                                                                

for key in s: print s[key]    

I can't understand why it produces the following output or how to get around it, any help greatly appreciated:

foo@bar:~$ python Settings.py
['SectionB', 'SectionA']
{'a': 1, 'c': 3, 'b': 2}
{'e': 5, 'd': 4, 'f': 6}
Traceback (most recent call last):
  File "Settings.py", line 20, in <module>
    for key in s: print s
  File "Settings.py", line 11, in __getitem__
    def __getitem__(self, key): return self.settings[key]
KeyError: 0
foo@bar:~$

That's because when you're iterating over the Settings class, it apparently tries to iterate over it by index, like a list. The first index is 0 , which gives a KeyError since it isn't in your dict. You have to define special methods to override the for key in s syntax to iterate over your keys.

def __iter__(self): return iter(self.settings)

Edit: One other thing is that you're using the deprecated old style classes. You should change it to Settings(object)

This works:

class Settings(dict):                                                                    
    """Singleton settings class"""                                              

    settings = {                                                                   
                   'SectionA': {'a': 1, 'b': 2, 'c': 3},                           
                   'SectionB': {'d': 4, 'e': 5, 'f': 6}                            
               }                                                                   

    def __getitem__(self, key): return self.settings[key]                          
    def __setitem__(self, key, item): self.settings[key] = item                    
    def keys(self): return self.settings.keys()                                    

s = Settings()                                                                     

for key in s.keys(): 
    print key 
    print s[key]

Prints:

SectionB
{'e': 5, 'd': 4, 'f': 6}
SectionA
{'a': 1, 'c': 3, 'b': 2}

Edit

Look ma, no {}.keys() :

class Settings(dict):                                                                    
    """Singleton settings class"""                                              

    settings = {                                                                   
                   'SectionA': {'a': 1, 'b': 2, 'c': 3},                           
                   'SectionB': {'d': 4, 'e': 5, 'f': 6}                            
               }                                                                   

    def __getitem__(self, key): return self.settings[key]                          
    def __setitem__(self, key, item): self.settings[key] = item  
    def __iter__(self): return iter(self.settings.keys())               
    def keys(self): return self.settings.keys()      


s = Settings()                                                                                                                                   

for key in s: 
    print key 
    print s[key]

Prints same output...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM