Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Python 3 dict question

38 views
Skip to first unread message

dmitrey

unread,
May 6, 2011, 3:40:13 PM5/6/11
to
hi all,
suppose I have Python dict myDict and I know it's not empty.
I have to get any (key, value) pair from the dict (no matter which
one) and perform some operation.
In Python 2 I used mere
key, val = myDict.items()[0]
but in Python 3 myDict.items() return iterator.
Of course, I could use
for key, val in myDict.items():
do_something
break
but maybe there is any better way?

Thank you in advance, D.

Chris Rebert

unread,
May 6, 2011, 3:51:27 PM5/6/11
to dmitrey, pytho...@python.org

key, val = next(myDict.items())

Cheers,
Chris

dmitrey

unread,
May 6, 2011, 3:57:11 PM5/6/11
to
On May 6, 10:51 pm, Chris Rebert <c...@rebertia.com> wrote:

Unfortunately, it doesn't work, it turn out to be dict_items:
>>> next({1:2}.items())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: dict_items object is not an iterator
>>> dir({1:2}.items())
['__and__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
'__ne__', '__new__', '__or__', '__rand__', '__reduce__',
'__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__',
'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__',
'__xor__', 'isdisjoint']

Ian Kelly

unread,
May 6, 2011, 4:02:23 PM5/6/11
to Python
On Fri, May 6, 2011 at 1:51 PM, Chris Rebert <cl...@rebertia.com> wrote:
> key, val = next(myDict.items())

Recognizing that if myDict is empty then this will raise StopIteration
instead of KeyError.

Rob Wolfe

unread,
May 6, 2011, 4:46:36 PM5/6/11
to
dmitrey <dmit...@gmail.com> writes:

key, val = next(iter(myDict.items()))

http://docs.python.org/py3k/library/stdtypes.html#dictionary-view-objects

HTH,
Rob

Ian Kelly

unread,
May 6, 2011, 4:48:45 PM5/6/11
to pytho...@python.org
On Fri, May 6, 2011 at 1:57 PM, dmitrey <dmit...@gmail.com> wrote:
> Unfortunately, it doesn't work, it turn out to be dict_items:
>>>> next({1:2}.items())
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: dict_items object is not an iterator

So call iter() on it first:

next(iter(myDict.items()))

nirinA raseliarison

unread,
May 6, 2011, 5:18:59 PM5/6/11
to Python List
[dmitrey]

key, val = list(myDict.items())[0]

--
nirinA

Ethan Furman

unread,
May 6, 2011, 6:49:40 PM5/6/11
to pytho...@python.org
Ian Kelly wrote:
> On Fri, May 6, 2011 at 1:57 PM, dmitrey <dmit...@gmail.com> wrote:
>> Unfortunately, it doesn't work, it turn out to be dict_items:
>>>>> next({1:2}.items())
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> TypeError: dict_items object is not an iterator
>
> So call iter() on it first:
>
> next(iter(myDict.items()))

Which is becoming less elegant. Seems to me that View objects should be
directly iterable, but then I don't really understand the motivation
behind them or what greatness is facilitated by having them.

Anybody care to chime in with their usage of this construct?

~Ethan~

Ian Kelly

unread,
May 6, 2011, 8:23:22 PM5/6/11
to Python
On Fri, May 6, 2011 at 4:49 PM, Ethan Furman <et...@stoneleaf.us> wrote:
> Ian Kelly wrote:
>>
>> On Fri, May 6, 2011 at 1:57 PM, dmitrey <dmit...@gmail.com> wrote:
>>>
>>> Unfortunately, it doesn't work, it turn out to be dict_items:
>>>>>>
>>>>>> next({1:2}.items())
>>>
>>> Traceback (most recent call last):
>>>  File "<stdin>", line 1, in <module>
>>> TypeError: dict_items object is not an iterator
>>
>> So call iter() on it first:
>>
>> next(iter(myDict.items()))
>
> Which is becoming less elegant.

That's not even the worst of it. If the dict is empty, then the code
above will raise a StopIteration, which must be caught locally since
if it propagates it could be swallowed by a generator. So a full
recipe should really look more like this:

try:
first_item = next(iter(my_dict.items()))
except StopIteration:
raise ValueError("empty dict")

> Seems to me that View objects should be directly iterable

They are. They're just not directly nextable because they're treated
as dependent collections, not iterators.

> but then I don't really understand the motivation behind them or what greatness is facilitated by having them.
>
> Anybody care to chime in with their usage of this construct?

You should start with PEP 3106. The main idea is that dict.keys() and
dict.items() can be treated as frozensets, while still being more
lightweight than lists. That lets you do nifty things like "a.keys()
== b.keys()" which, if a and b are Python 3 dicts, will tell you
whether they contain the same keys.

Whether anybody actually uses this, I have no idea.

Gregory Ewing

unread,
May 7, 2011, 5:09:09 AM5/7/11
to
Ethan Furman wrote:

> Ian Kelly wrote:
>
>> next(iter(myDict.items()))
>
> Which is becoming less elegant.

If you're doing this sort of thing a lot you can make
a little helper function:

def first(x):
return next(iter(x))

then you get to say

first(myDict.items())

--
Greg

Thomas Rachel

unread,
May 8, 2011, 5:23:48 AM5/8/11
to

... and get a StopIteration if the dict is empty.

If you do

def first(x, default=None):
for i in x:
return i
return default

you might have an alternative approach to do so.


Thomas

Ethan Furman

unread,
May 10, 2011, 1:18:53 PM5/10/11
to Ian Kelly, Python
Ian Kelly wrote:

> On Fri, May 6, 2011 at 4:49 PM, Ethan Furman wrote:
>> Anybody care to chime in with their usage of this construct?
>
> You should start with PEP 3106. The main idea is that dict.keys() and
> dict.items() can be treated as frozensets, while still being more
> lightweight than lists. That lets you do nifty things like "a.keys()
> == b.keys()" which, if a and b are Python 3 dicts, will tell you
> whether they contain the same keys.

Cool, thanks.

~Ethan~

Raymond Hettinger

unread,
May 10, 2011, 1:25:54 PM5/10/11
to

If your use case allows the item to be removed, then use:

key, val = myDict.popitem()

Otherwise, use:

key, val = next(iter(MyDict.items()))

The latter is nice because next() allows you to supply a default
argument in case the dictionary is emtpy:

key, val = next(iter(MyDict.items()), (None, None))

Raymond

---------
follow my tips and recipes on twitter: @raymondh


0 new messages