Reputation: 1673
I have a dict
like this:
>>> my_dict = {u'2008': 6.57, u'2009': 4.89, u'2011': 7.74,
... u'2010': 7.44, u'2012': 7.44}
Output with has_key
:
>>> my_dict.has_key(unicode(2012))
True
Output with hasattr
:
>>> hasattr(my_dict, unicode(2012))
False
I couldn't understand why this behaves differently.
I googled and found out that it is because dict
and objects are different.
But, still I couldn't understand the difference properly.
(BTW : I am using python 2.7)
Upvotes: 19
Views: 20905
Reputation: 1399
attribute
returns some property of an instance so that you can manipulate it.
Now understand attribute
will always return something, but if a key
is not in d
, d[key]
will raise KeyError
.
hasattr
checks if an instantce
has that attribute
or not. Since dictionary
keys
are no attribute
to the dictionary
it returns False
.
example :
# 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
Upvotes: 0
Reputation: 3188
Dict is an object, as anything in Python is an object. There's, however, a difference between an objects attribute and a dicts key.
The dict doesn't store its keys as attributes!
The only way to access a dicts keys is through the __getitem__
method or the []
operator.
If you want to access the items this way, you can override the __getattr__
method and make it return the __getitem__
result in stead.
You can also create something like this:
class ObjectDict(dict):
def __init__(self, *args, **kws):
super(ObjectDict, self).__init__(*args, **kws)
self.__dict__ = self
Which will result in this behavior:
>>> d = ObjectDict() >>> d['a'] = 3 >>> d.a 3 >>> hasattr(d, 'a') True
But this is known to cause memory leaks in Python
Upvotes: 1
Reputation: 1123360
dict
instances are objects too. But their keys are just not exposed as as attributes.
Exposing the keys as attributes (too or instead of item access) would lead to namespace pollution; you'd never be able to use a has_key
key, for example. has_key
is already an attribute on dictionaries:
>>> hasattr({}, 'has_key')
True
>>> {}.has_key
<built-in method has_key of dict object at 0x7fa2a8461940>
Attributes of objects and the contents of dictionaries are two separate things, and the separation is deliberate.
You can always subclass dict
to add attribute access using the __getattr__()
hook method:
class AttributeDict(dict):
def __getattr__(self, name):
if name in self:
return self[name]
raise AttributeError(name)
Demo:
>>> demo = AttributeDict({'foo': 'bar'})
>>> demo.keys()
['foo']
>>> demo.foo
'bar'
Existing attributes on the dict
class take priority:
>>> demo['has_key'] = 'monty'
>>> demo.has_key
<built-in method has_key of AttributeDict object at 0x7fa2a8464130>
Upvotes: 33
Reputation: 26333
my_dict.has_key(unicode(2012))
: has_key
looks for a key in a dictionary. Keys in a dictionary are not attributes and
hasattr(object, name)
The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if not. (This is implemented by calling getattr(object, name) and seeing whether it raises an exception or not.)
from which you can see that, although dict are objects, dict's keys are not the dict's attributes;
Upvotes: 2
Reputation: 34513
has_key
checks for the existence of a key in the dictionary. (One your code defines while creating a dictionary) hasattr
checks if the object has an attribute.
Dictionaries are objects, and they have certain attributes. hasattr
checks for those.
>>> hasattr(dict, 'has_key')
True
>>> hasattr(dict, 'items')
True
>>> newDict = {'a': 1, 'b':2}
>>> newDict.has_key('a')
True
You can use dir()
which lists out the valid attributes for an object.
>>> 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']
Upvotes: 3