18

我有一个dict这样的:

>>> my_dict = {u'2008': 6.57, u'2009': 4.89, u'2011': 7.74,
...            u'2010': 7.44, u'2012': 7.44}

输出has_key

>>> my_dict.has_key(unicode(2012))
True

输出hasattr

>>> hasattr(my_dict, unicode(2012))
False

我不明白为什么这会表现不同。我用谷歌搜索发现这是因为dict和对象不同。

但是,我仍然无法正确理解差异。

(顺便说一句:我使用的是 python 2.7)

4

5 回答 5

31

dict实例也是对象。但是它们的键并没有作为属性公开。

将键暴露为属性(也或代替项目访问)会导致命名空间污染;例如,您永远无法使用has_key密钥。已经has_key是字典上的一个属性:

>>> hasattr({}, 'has_key')
True
>>> {}.has_key
<built-in method has_key of dict object at 0x7fa2a8461940>

对象的属性和字典的内容是两个分开的东西,分开是故意的。

您始终可以使用钩子方法dict进行子类化以添加属性访问:__getattr__()

class AttributeDict(dict):
    def __getattr__(self, name):
        if name in self:
            return self[name]
        raise AttributeError(name)

演示:

>>> demo = AttributeDict({'foo': 'bar'})
>>> demo.keys()
['foo']
>>> demo.foo
'bar'

类上的现有属性dict优先:

>>> demo['has_key'] = 'monty'
>>> demo.has_key
<built-in method has_key of AttributeDict object at 0x7fa2a8464130>
于 2013-07-20T10:25:56.257 回答
3

has_key检查字典中是否存在键。(您的代码在创建字典时定义)hasattr检查对象是否具有属性。

字典是对象,它们具有某些属性。hasattr检查那些。

>>> hasattr(dict, 'has_key')
True
>>> hasattr(dict, 'items')
True
>>> newDict = {'a': 1, 'b':2}
>>> newDict.has_key('a')
True

您可以使用dir()which 列出对象的有效属性。

>>> dir(dict)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']
于 2013-07-20T10:25:22.587 回答
2

my_dict.has_key(unicode(2012)):has_key在字典中查找键。字典中的键不是属性,而是

hasattr(对象,名称)

参数是一个对象和一个字符串。如果字符串是对象属性之一的名称,则结果为 True,否则为 False。(这是通过调用 getattr(object, name) 并查看它是否引发异常来实现的。)

从中可以看出,虽然 dict 是对象,但 dict 的键不是 dict 的属性;

于 2013-07-20T10:38:19.510 回答
1

Dict 是一个对象,就像 Python 中的任何东西都是一个对象一样。但是,objects 属性和 dicts 键之间存在差异。dict 不会将其键存储为属性!访问 dicts 键的唯一方法是通过__getitem__方法或[]运算符。

如果您想以这种方式访问​​项目,您可以覆盖该__getattr__方法并使其返回__getitem__结果。

您还可以创建如下内容:

   class ObjectDict(dict):
       def __init__(self, *args, **kws):
           super(ObjectDict, self).__init__(*args, **kws)
           self.__dict__ = self

这将导致这种行为:

>>> d = ObjectDict()
>>> d['a'] = 3
>>> 达
3
>>> hasattr(d, 'a')
真的

但这会导致 Python 中的内存泄漏

于 2013-07-20T10:28:50.397 回答
0

attribute返回实例的某些属性,以便您可以操作它。现在了解attribute总是会返回一些东西,但是如果 akey不在dd[key]就会提高KeyError

hasattr检查是否instantceattribute。既然dictionary keys都没有它attribute返回。dictionaryFalse

例子 :

# python3
>>> d = {1:True}
>>> dir(d) # this shows all the attributes of the instance
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__'
, '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__',
 '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '_
_new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__'
, '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get
', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
>>> hasattr(d,'keys')
True
>>> 1 in d.keys()
True
于 2013-07-20T10:25:56.473 回答