2012-05-23 116 views
14

我有时收到不存在的键调用一个字典,所以我尝试使用hasattrgetattr处理这些情况:Python的hasattr字典的列表值总是返回false?

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返回false,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()已被弃用,由PEP 8风格指南建议反对,并已在Python 3

完全取消顺便说一句,

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

初始化它在你__init__代替:

012你会用可变类变量遇到问题
class State(object): 
    info = None 

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

我会被诅咒的!我以为我疯了。我一直使用'if/in/else'结构来处理这些带默认值的字典测试情况。这一次,由于实际情况实际上比我的例子复杂得多,还有其他一些hasattrs飞来飞去,我赞成“语法”,而不是......这显然不起作用!我从现在开始会记住这个问题,谢谢! –

+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:

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

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

看起来像所有你需要的是一个行:

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

这是很方便的定义反射从对象获取属性或密钥的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