【问题标题】:Python's hasattr on list values of dictionaries always returns false?Python的字典列表值的hasattr总是返回false?
【发布时间】:2012-05-30 06:51:54
【问题描述】:

我的字典有时会收到不存在的键的调用,因此我尝试使用 hasattrgetattr 来处理这些情况:

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的值!这是为什么呢?

【问题讨论】:

    标签: python list class dictionary hasattr


    【解决方案1】:

    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__ 中初始化它:

    class State(object):
        info = None
    
        def __init__(self):
            self.info = {}
    

    【讨论】:

    • 我该死!我以为我快疯了。对于这些使用默认值的字典测试情况,我一直使用if/in/else 结构。这一次,由于实际情况实际上比我的示例要复杂得多,而且还有一些其他的 hasattr 飞来飞去,所以我更喜欢那个“语法”……这显然行不通!从现在开始我会记住这个问题,谢谢!
    • 另外,我正在适当地处理 init 中的信息,只是想简化示例。
    【解决方案2】:

    字典键与对象属性不同

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

    【讨论】:

    • 啊。这让我发疯了。感谢分享示例。
    【解决方案3】:

    要测试列表/字典中的元素,请使用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
    

    或者使用默认字典:

    from collections import defaultdict
    class State(object):
        info = defaultdict(list)
    
        def add_to_info(self, key_string, integer):
            self.info[key_string].append(integer)
    

    【讨论】:

      【解决方案4】:

      看起来你只需要一行:

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

      【讨论】:

        【解决方案5】:

        您可以在 dict 类型对象上使用 .get() 方法。如果未定义,此方法不会引发关键错误。此外,作为对象的 getattr(),您可以在其上指定默认值。

        >> {'name': 'Me'}.get('name1', 'StackOverflow')
        >> 'StackOverflow'
        

        【讨论】:

          猜你喜欢
          • 2015-07-24
          • 2018-11-10
          • 1970-01-01
          • 2017-11-23
          • 2021-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多