2012-05-23 6 views
14

मैं एक शब्दकोश है कि कभी कभी गैर-मौजूद कुंजियों के लिए कॉल प्राप्त है, तो मैं कोशिश करते हैं और इन मामलों को संभालने के लिए hasattr और getattr का उपयोग करें:शब्दकोशों की सूची मूल्यों पर पाइथन का हैटट्रर हमेशा झूठा देता है?

key_string = 'foo' 
print "current info:", info 
print hasattr(info, key_string) 
print getattr(info, key_string, []) 
if hasattr(info, key_string): 
    array = getattr(info, key_string, []) 
array.append(integer) 
info[key_string] = array 
print "current info:", info 

integer = 1 के साथ पहली बार इस चलाता है:

current info: {} 
False 
[] 
current info: {'foo': [1]} 

integer = 2 के साथ फिर से इस कोड चल रहा है:

instance.add_to_info("foo", 2) 

current info: {'foo': [1]} 
False 
[] 
current info: {'foo': [2]} 

पहला रन स्पष्ट रूप से सफल है ({'foo': [1]}), लेकिन hasattr झूठी रिटर्न देता है और getattr प्रक्रिया में 1 के मान को खोने के दौरान दूसरी बार डिफ़ॉल्ट रिक्त सरणी का उपयोग करता है! ऐसा क्यों है?

उत्तर

21

hasattr विशेषता एक शब्दकोश के सदस्यों के लिए इसका परीक्षण नहीं होता नहीं है। in ऑपरेटर के बजाय, या .has_key विधि का उपयोग करें:

>>> example = dict(foo='bar') 
>>> 'foo' in example 
True 
>>> example.has_key('foo') 
True 
>>> 'baz' in example 
False 

लेकिन ध्यान दें कि dict.has_key() पदावनत किया गया है, पीईपी 8 शैली गाइड द्वारा के खिलाफ की सिफारिश की है और संयोग से अजगर 3.

में पूरी तरह हटा दिया गया है,

012:

>>> class example(object): 
...  foo = dict() 
... 
>>> A = example() 
>>> B = example() 
>>> A.foo['bar'] = 'baz' 
>>> B.foo 
{'bar': 'baz'} 

बजाय अपने __init__ में यह प्रारंभ: यदि आप एक परिवर्तनशील वर्ग चर का उपयोग करके समस्याएं आ जाएगा

class State(object): 
    info = None 

    def __init__(self): 
     self.info = {} 
+0

मैं शापित हो जाऊंगा! मैने सोचा मैं पागल हो गया था। मैंने डिफ़ॉल्ट रूप से इन शब्दकोश परीक्षण स्थितियों के लिए हमेशा 'if/in/else' संरचना का उपयोग किया है। इस बार वास्तविक स्थिति वास्तव में मेरे उदाहरण की तुलना में अधिक जटिल है, कुछ अन्य हैटर्स उड़ान भरने के साथ, मैंने इसके बजाय "वाक्यविन्यास" का पक्ष लिया ... जो स्पष्ट रूप से काम नहीं करता है! मुझे अब से यह गोचा याद होगा, धन्यवाद! –

+0

इसके अलावा, मैं उचित रूप से init में जानकारी से निपट रहा हूं, बस उदाहरण को व्यवस्थित करना चाहता था। –

2

एक शब्दकोश कुंजी एक ही रूप में एक वस्तु

thing1 = {'a', 123} 
hasattr(thing1, 'a') # False 
class c: pass 
thing2 = c() 
thing2.a = 123 
hasattr(thing2, 'a') # True 
1

किसी सूची/शब्दकोश में तत्वों के परीक्षण के लिए, in का उपयोग करें। डिफ़ॉल्ट का उपयोग करने के लिए आपको dict.get उपयोग कर सकते हैं:

def add_to_info(self, key_string, integer): 
    array = self.info.get(key_string, []) 
    array.append(integer) 
    self.info[key_string] = array 

या defaultdict का उपयोग करें:

def add_to_info(self, key_string, integer): 
    self.info.setdefault(key_string, []).append(integer) 
2

आप सभी की जरूरत की तरह लग रहा एक पंक्ति है getAttr जो किसी ऑब्जेक्ट से विशेषताएँ या कुंजी प्राप्त करता है।

def getAttr(obj, attribute, default=''): 

    # like getattr, but also check the keys of obj, and can return a default, if no key or no attribute was found. 
    # note there's a priority to attribute if both attribute and key exist. 

    result = getattr(obj, attribute) if hasattr(obj, attribute) else None 
    if result is None: 
    result = obj.get(attribute, default) if isinstance(obj, dict) else default 
    return result 
0

यह एक चिंतनशील परिभाषित किया है करने के लिए आसान है:

from collections import defaultdict 
class State(object): 
    info = defaultdict(list) 

    def add_to_info(self, key_string, integer): 
     self.info[key_string].append(integer)