Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #51161 > unrolled thread

Re: Python 3: dict & dict.keys()

Started byEthan Furman <ethan@stoneleaf.us>
First post2013-07-24 11:31 -0700
Last post2013-07-25 18:25 +0200
Articles 8 — 6 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Python 3: dict & dict.keys() Ethan Furman <ethan@stoneleaf.us> - 2013-07-24 11:31 -0700
    Re: Python 3: dict & dict.keys() alex23 <wuwei23@gmail.com> - 2013-07-25 16:01 +1000
      Re: Python 3: dict & dict.keys() Ethan Furman <ethan@stoneleaf.us> - 2013-07-25 06:47 -0700
    Re: Python 3: dict & dict.keys() Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-07-25 07:04 +0000
      Re: Python 3: dict & dict.keys() Chris Angelico <rosuav@gmail.com> - 2013-07-25 18:02 +1000
      Re: Python 3: dict & dict.keys() Peter Otten <__peter__@web.de> - 2013-07-25 10:13 +0200
      Re: Python 3: dict & dict.keys() Ian Kelly <ian.g.kelly@gmail.com> - 2013-07-25 09:53 -0600
      Re: Python 3: dict & dict.keys() Peter Otten <__peter__@web.de> - 2013-07-25 18:25 +0200

#51161 — Re: Python 3: dict & dict.keys()

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-24 11:31 -0700
SubjectRe: Python 3: dict & dict.keys()
Message-ID<mailman.5061.1374692206.3114.python-list@python.org>
On 07/24/2013 10:23 AM, Stefan Behnel wrote:
> Peter Otten, 24.07.2013 08:23:
>> Ethan Furman wrote:
>>>
>>> So, my question boils down to:  in Python 3 how is dict.keys() different
>>> from dict?  What are the use cases?
>>
>> To me it looks like views are a solution waiting for a problem.
>
> They reduce the API overhead. Previously, you needed values() and
> itervalues(), with values() being not more than a special case of what
> itervalues() provides anyway. Now it's just one method that gives you
> everything. It simply has corrected the tradeoff from two special purpose
> APIs to one general purpose API, that's all.

I started this thread for two reasons:

   1) Increase awareness that using `list(dict)` is a cross-version replacement for `dict.keys()`

   2) Hopefully learn something about when a view is useful.

So far #2 is pretty much a failure.  Only one use-case so far (and it feels pretty rare).  But hey, I have learned that 
while some set operations are allowed (&, ^, |, .isdisjoint()), others are not (.remove(), .discard(), .union(), etc.).

The old .keys(), .values(), and .items() (and their .iter...() variations) did something commonly useful.  Of what 
common use are these views?

--
~Ethan~

[toc] | [next] | [standalone]


#51192

Fromalex23 <wuwei23@gmail.com>
Date2013-07-25 16:01 +1000
Message-ID<ksqeju$5s7$1@dont-email.me>
In reply to#51161
On 25/07/2013 4:31 AM, Ethan Furman wrote:
>    2) Hopefully learn something about when a view is useful.

I haven't seeen this mentioned - forgive me if it's a repeat - but views 
are constant references to whichever set they represent.

Python 2.7:

 >>> dd = dict(a=1,b=2,c=3)
 >>> keys = dd.keys()
 >>> 'a' in keys
True
 >>> dd['d'] = 4
 >>> 'd' in keys
False

Python 3.3:
 >>> dd = dict(a=1,b=2,c=3)
 >>> keys = dd.keys()
 >>> 'a' in keys
True
 >>> dd['d'] = 4
 >>> 'd' in keys
True

If part of my code is only interested in what keys or values are 
present, it doesn't need to be given a reference to the full dictionary, 
just to whichever view it cares about.

[toc] | [prev] | [next] | [standalone]


#51227

FromEthan Furman <ethan@stoneleaf.us>
Date2013-07-25 06:47 -0700
Message-ID<mailman.5102.1374762804.3114.python-list@python.org>
In reply to#51192
On 07/24/2013 11:01 PM, alex23 wrote:
> On 25/07/2013 4:31 AM, Ethan Furman wrote:
>>    2) Hopefully learn something about when a view is useful.
>
> I haven't seeen this mentioned - forgive me if it's a repeat - but views are constant references to whichever set they
> represent.
>
> Python 2.7:
>
>>>> dd = dict(a=1,b=2,c=3)
>>>> keys = dd.keys()
>>>> 'a' in keys
> True
>>>> dd['d'] = 4
>>>> 'd' in keys
> False
>
> Python 3.3:
>>>> dd = dict(a=1,b=2,c=3)
>>>> keys = dd.keys()
>>>> 'a' in keys
> True
>>>> dd['d'] = 4
>>>> 'd' in keys
> True
>
> If part of my code is only interested in what keys or values are present, it doesn't need to be given a reference to the
> full dictionary, just to whichever view it cares about.

In these cases why is a view better than just using the dict?  Is it a safety so the you don't accidentally modify the dict?

--
~Ethan~

[toc] | [prev] | [next] | [standalone]


#51198

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-07-25 07:04 +0000
Message-ID<51f0ce06$0$29971$c3e8da3$5496439d@news.astraweb.com>
In reply to#51161
On Wed, 24 Jul 2013 11:31:58 -0700, Ethan Furman wrote:

> On 07/24/2013 10:23 AM, Stefan Behnel wrote:
>> Peter Otten, 24.07.2013 08:23:
>>> Ethan Furman wrote:
>>>>
>>>> So, my question boils down to:  in Python 3 how is dict.keys()
>>>> different from dict?  What are the use cases?
>>>
>>> To me it looks like views are a solution waiting for a problem.
>>
>> They reduce the API overhead. Previously, you needed values() and
>> itervalues(), with values() being not more than a special case of what
>> itervalues() provides anyway. Now it's just one method that gives you
>> everything. It simply has corrected the tradeoff from two special
>> purpose APIs to one general purpose API, that's all.
> 
> I started this thread for two reasons:
> 
>    1) Increase awareness that using `list(dict)` is a cross-version
>    replacement for `dict.keys()`
> 
>    2) Hopefully learn something about when a view is useful.
> 
> So far #2 is pretty much a failure.

I don't think so.

- viewkeys() can be used as a drop-in replacement for iterkeys(), 
provided you remember not to iterate over it a second time. Doing so 
actually iterates over the view, instead of failing as with the iterator. 
If you actually want a one-shot iterator, call iter() on the view.

- viewkeys() can be used as a drop-in replacement for Python2 keys(), 
provided you only iterate over it once. If you want an actual list, call 
list() on the view.

- Views support set methods which don't modify the set. If there is a non-
modifying set method which is not supported, it probably should be, and 
somebody should raise an enhancement request in the bug tracker. If you 
want an actual independent set you can modify without changing the dict, 
call set() (or frozenset) on the view.

- Views support efficient (O(1) in the case of keys) membership testing, 
which neither iterkeys() nor Python2 keys() does.

- Views support live, read-only access to dict keys and values.



> Only one use-case so far (and it
> feels pretty rare).

Iterating over a dict's values or items is not rare. Using a view is 
better than making a list-copy of the dict and iterating over the list, 
because it avoids copying.

For one-shot iteration, there's no benefit of a view over an iterator, or 
vice versa, but views are useful for more than just one-shot iteration.



> But hey, I have learned that while some set
> operations are allowed (&, ^, |, .isdisjoint()), others are not
> (.remove(), .discard(), .union(), etc.).
> 
> The old .keys(), .values(), and .items() (and their .iter...()
> variations) did something commonly useful.  Of what common use are these
> views?

Everything that dict iteration does, dict views do, and more. So if 
iterkeys() is useful, then so is viewkeys(). Had viewkeys come first, 
iterkeys would never have been invented.

Making an actual list copy of the keys (values, items) is useful, but 
it's not useful enough to dedicate a method (three methods) for it. Just 
call list() on the view (or, in the case of keys, directly on the dict).



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#51204

FromChris Angelico <rosuav@gmail.com>
Date2013-07-25 18:02 +1000
Message-ID<mailman.5085.1374739334.3114.python-list@python.org>
In reply to#51198
On Thu, Jul 25, 2013 at 5:04 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> - Views support efficient (O(1) in the case of keys) membership testing,
> which neither iterkeys() nor Python2 keys() does.

To save me the trouble and potential error of digging through the
source code: What's the complexity of membership testing on
values/items? Since you're calling it "efficient" it must be better
than O(n) which the list form would be, yet it isn't O(1) or you
wouldn't have qualified "in the case of keys". Does this mean
membership testing of the values and items views is O(log n) in some
way, eg a binary search?

ChrisA

[toc] | [prev] | [next] | [standalone]


#51205

FromPeter Otten <__peter__@web.de>
Date2013-07-25 10:13 +0200
Message-ID<mailman.5086.1374740010.3114.python-list@python.org>
In reply to#51198
Chris Angelico wrote:

> On Thu, Jul 25, 2013 at 5:04 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> - Views support efficient (O(1) in the case of keys) membership testing,
>> which neither iterkeys() nor Python2 keys() does.
> 
> To save me the trouble and potential error of digging through the
> source code: What's the complexity of membership testing on
> values/items? Since you're calling it "efficient" it must be better
> than O(n) which the list form would be, yet it isn't O(1) or you
> wouldn't have qualified "in the case of keys". Does this mean
> membership testing of the values and items views is O(log n) in some
> way, eg a binary search?

keys() and items() is O(1); both look up the key in the dictionary and 
items() then proceeds to compare the value. values() is O(n).

[toc] | [prev] | [next] | [standalone]


#51237

FromIan Kelly <ian.g.kelly@gmail.com>
Date2013-07-25 09:53 -0600
Message-ID<mailman.5107.1374767657.3114.python-list@python.org>
In reply to#51198
On Thu, Jul 25, 2013 at 2:13 AM, Peter Otten <__peter__@web.de> wrote:
> Chris Angelico wrote:
>
>> On Thu, Jul 25, 2013 at 5:04 PM, Steven D'Aprano
>> <steve+comp.lang.python@pearwood.info> wrote:
>>> - Views support efficient (O(1) in the case of keys) membership testing,
>>> which neither iterkeys() nor Python2 keys() does.
>>
>> To save me the trouble and potential error of digging through the
>> source code: What's the complexity of membership testing on
>> values/items? Since you're calling it "efficient" it must be better
>> than O(n) which the list form would be, yet it isn't O(1) or you
>> wouldn't have qualified "in the case of keys". Does this mean
>> membership testing of the values and items views is O(log n) in some
>> way, eg a binary search?
>
> keys() and items() is O(1); both look up the key in the dictionary and
> items() then proceeds to compare the value. values() is O(n).

3.x values() is O(n) but avoids the unnecessary step of copying all the
values in the dict that you get when performing the same operation
using 2.x values().  Hence, although the asymptotic complexity is the
same, it's still more efficient.

[toc] | [prev] | [next] | [standalone]


#51243

FromPeter Otten <__peter__@web.de>
Date2013-07-25 18:25 +0200
Message-ID<mailman.5111.1374769510.3114.python-list@python.org>
In reply to#51198
Ian Kelly wrote:

> On Thu, Jul 25, 2013 at 2:13 AM, Peter Otten <__peter__@web.de> wrote:
>> Chris Angelico wrote:
>>
>>> On Thu, Jul 25, 2013 at 5:04 PM, Steven D'Aprano
>>> <steve+comp.lang.python@pearwood.info> wrote:
>>>> - Views support efficient (O(1) in the case of keys) membership
>>>> testing, which neither iterkeys() nor Python2 keys() does.
>>>
>>> To save me the trouble and potential error of digging through the
>>> source code: What's the complexity of membership testing on
>>> values/items? Since you're calling it "efficient" it must be better
>>> than O(n) which the list form would be, yet it isn't O(1) or you
>>> wouldn't have qualified "in the case of keys". Does this mean
>>> membership testing of the values and items views is O(log n) in some
>>> way, eg a binary search?
>>
>> keys() and items() is O(1); both look up the key in the dictionary and
>> items() then proceeds to compare the value. values() is O(n).
> 
> 3.x values() is O(n) but avoids the unnecessary step of copying all the
> values in the dict that you get when performing the same operation
> using 2.x values().  Hence, although the asymptotic complexity is the
> same, it's still more efficient.

In Python 2 the prudent pythonista used itervalues() to avoid unnecessary 
intermediate list...

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web