[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Serhiy Storchaka

25.07.19 01:15, Greg Ewing пише:

Steven D'Aprano wrote:
Currently that assertion fails. Should it? Putting aside the 
convenience of "do nothing, just inherit the object.__eq__ behaviour" 
do you think that the current behaviour is *correct*?


What I'm getting from this thread is that there are a variety of
possible behaviours for dict values comparison, any of which could
be considered "correct" depending on what the programmer is trying
to do.

I know there are good reasons for the guideline that equality
comparisons should never raise exceptions, but this seems like a
situation where Python really should slap you on the ear and
make you specify exactly what you want.


Is there any precedence of raising an exception in the equality comparison?

Does 3 == "3" returning False make more sense to you?
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/56T2IDDMFZ27W37TQ7RVE5OO3WRVVKME/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
Serhiy Storchaka wrote:
> Is there any precedence of raising an exception in the equality comparison?
> Does 3 == "3" returning False make more sense to you?

Personally, I don't find ``3 == "3"`` to be an equivalent comparison to 
``d0.values() == d1.values()``. Generally, it makes sense when comparing two 
items of different types, they are not going to be equivalent (except in cases 
such as ``3 == 3.0``, but in that case they are both subtypes of numeric). 

I don't know that an exception would be the best behavior to suit this 
situation (or for anything using ``__eq__`` for that matter), but returning 
``False`` seems to be a bit misleading. Instead, I think that either returning 
the ``NotImplemented`` constant or ``None`` would provide far more useful 
information to the user, without the hindrance of causing an exception. I'm 
leaning more favorably towards ``NotImplemented`` because it explicitly tells 
the user "Hey, that equality comparison isn't implemented".
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/SJKDNGBIEBCL67NWL7CPGTVNSY2QLXBD/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Petr Viktorin

On 7/25/19 2:25 AM, David Mertz wrote:
Exactly! that was my thought that the exception message could hint at 
likely approaches. The NumPy example seems to have a good pattern:


arr1 == arr2

|ValueError:Thetruth value of an array withmore than one element |isambiguous.

|Usea.any()ora.all().|


It's not the equality operator that errors: `==` means element-wise 
comparison in Numpy.

The error would come from a conversion of the array to bool:

>>> numpy.array([1, 2, 3]) == numpy.array([1, 3, 4])
array([ True, False, False])

>>> if numpy.array([ True, False, False]):
... print('Same!')
...
Traceback (most recent call last):
  File "", line 1, in 
ValueError: The truth value of an array with more than one element is 
ambiguous. Use a.any() or a.all()



Numpy currently returns False when `==` “doesn't make sense”, but 
apparently has plans to change that:


>>> numpy.array([1, 2, 3]) == numpy.array([1, 2])
__main__:1: DeprecationWarning: elementwise comparison failed; this will 
raise an error in the future.

False

>>> numpy.array([1, 2, 3]) == numpy.array(['a', 'b'])
__main__:1: FutureWarning: elementwise comparison failed; returning 
scalar instead, but in the future will perform elementwise comparison

False

>>> numpy.__version__
'1.16.4'





On Wed, Jul 24, 2019, 8:06 PM Rob Cliffe via Python-Dev 
mailto:python-dev@python.org>> wrote:




On 25/07/2019 00:09:37, David Mertz wrote:
 > I agree with Greg.
 >
 > There are various possible behaviors that might make sense, but
having
 > `d.values() != d.values()` is about the only one I can see no
sense in.
+1
 >
 > This really feels like a good cade for reading a descriptive
 > exception. If someone wants too compare `set(d.values())` that's
 > great. If they want `list(d.values())`, also a sensible question.
But
 > the programmer should spell it explicitly.
 >
 >
So, a helpful error message including something like "Cannot compare
dict.values directly, consider converting to sets / lists / sorted
lists
before comparing" ?
___
Python-Dev mailing list -- python-dev@python.org

To unsubscribe send an email to python-dev-le...@python.org

https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at

https://mail.python.org/archives/list/python-dev@python.org/message/CSTSLCDEJYKDLADQV5PJRCSSVTMB5RIG/


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/2IMLY36A6K45LHCXO2OVQJZBQKL47U6T/


___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/DRG757EQKEDNKPPM2KXMZ5NVVSBSGMCL/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Steve Holden
On Thu, Jul 25, 2019 at 4:01 AM Rob Cliffe via Python-Dev <
python-dev@python.org> wrote:

> I considered an alternative: return True if the underlying dicts were
> identical or equal, and raise an Exception otherwise.
> But I soon decided that this was a terrible idea: it could hide a bug by
> making faulty code work intermittently.
> Apologies for doubtless belabouring the blindingly obvious (but then
> again, if I don't mention this possibility, maybe someone even more
> idiotic than me will suggest it ).
>
>
Whatever made you think I'd do that?
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/F6EPXBDDOJX6PKNRMGESBG3EMJ63VNBV/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Eric V. Smith




On 7/25/2019 4:27 AM, Kyle Stanley wrote:

Serhiy Storchaka wrote:

Is there any precedence of raising an exception in the equality comparison?
Does 3 == "3" returning False make more sense to you?


Personally, I don't find ``3 == "3"`` to be an equivalent comparison to 
``d0.values() == d1.values()``. Generally, it makes sense when comparing two items of 
different types, they are not going to be equivalent (except in cases such as ``3 == 
3.0``, but in that case they are both subtypes of numeric).

I don't know that an exception would be the best behavior to suit this situation (or for 
anything using ``__eq__`` for that matter), but returning ``False`` seems to be a bit 
misleading. Instead, I think that either returning the ``NotImplemented`` constant or 
``None`` would provide far more useful information to the user, without the hindrance of 
causing an exception. I'm leaning more favorably towards ``NotImplemented`` because it 
explicitly tells the user "Hey, that equality comparison isn't implemented".


That makes things worse. Now the comparison is always true in a boolean 
context. And presumably you'd want __ne__ to also return NotImplemented, 
so then both __eq__ and __ne__ would be true, since bool(NotImplemented) 
is True.


Eric
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/4JDULEU72MK6GKPYAABVDWQY2CTUJVCX/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Eric V. Smith

7/25/2019 6:00 AM, Eric V. Smith wrote:



On 7/25/2019 4:27 AM, Kyle Stanley wrote:

Serhiy Storchaka wrote:
Is there any precedence of raising an exception in the equality 
comparison?

Does 3 == "3" returning False make more sense to you?


Personally, I don't find ``3 == "3"`` to be an equivalent comparison 
to ``d0.values() == d1.values()``. Generally, it makes sense when 
comparing two items of different types, they are not going to be 
equivalent (except in cases such as ``3 == 3.0``, but in that case 
they are both subtypes of numeric).


I don't know that an exception would be the best behavior to suit this 
situation (or for anything using ``__eq__`` for that matter), but 
returning ``False`` seems to be a bit misleading. Instead, I think 
that either returning the ``NotImplemented`` constant or ``None`` 
would provide far more useful information to the user, without the 
hindrance of causing an exception. I'm leaning more favorably towards 
``NotImplemented`` because it explicitly tells the user "Hey, that 
equality comparison isn't implemented".


That makes things worse. Now the comparison is always true in a boolean 
context. And presumably you'd want __ne__ to also return NotImplemented, 
so then both __eq__ and __ne__ would be true, since bool(NotImplemented) 
is True.


I might have to take that back. I hadn't factored in what the == and != 
machinery does, beyond calling __eq__ or __ne__.


Eric
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/C3RNFXQ75J57BD46JXUVPBGLMKAW6XOD/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Antoine Pitrou
On Wed, 24 Jul 2019 19:09:37 -0400
David Mertz  wrote:
> 
> There are various possible behaviors that might make sense, but having
> `d.values() != d.values()` is about the only one I can see no sense in.

Why? Does the following make no sense to you?

>>> iter(()) == iter(())
False

Python deliberately allows you to compare everything with everything,
at least for equality.  Perhaps it shouldn't, but it's too late to
design the language differently.

> This feels similar to NumPy arrays, that also will not compare for equality
> in bare form.

They will, but then they return an array of booleans.

>>> a = np.array([1,2])
>>> b = np.array([1,3])
>>> a == b   
array([ True, False])

Regards

Antoine.

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/22MR5JGSMPOES6FJMVFTBOOMRXCU7DIK/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Brett Cannon
Steven D'Aprano wrote:
> On Wed, Jul 24, 2019 at 05:30:19PM -, Brett Cannon wrote:
> > When I saw this I thought, "it should be like
> > set(d1.values()) == 
> > set(d2.values())", but has been pointed out there's no guarantee that 
> > all values will be hashable.
> > The hashability requirement for sets is, in a sense, an implementation 
> detail. It might be a requirement for sets in Python the language, 
> but its not a requirement for abstract "sets of values".
> E.g. Java includes a standard TreeSet which doesn't require hashability
> https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html
> In this case, they need to be multisets, since
> {'a': 1, 'b': 2, 'c': 1}.values() != {'a': 1, 'b': 2, 'c': 2}.values()
> > After that I have no expectation since order isn't
> > guaranteed.
> > I think this is one of those cases where it's superficially surprising 
> > when you don't think about all the ramifications, but once you 
> > understand the complexity of the problem then it becomes more clear 
> > that it isn't straight-forward.
> > Nobody said it was straight-forward, particularly if we want guaranteed 
> efficient comparisons in both time and space at the same time.
> Brett, I feel that you are dismissing this thread as "not thinking 
> through the ramifications" without reading it through, because I'm 
> pretty sure that we have thought through the ramifications in a lot more 
> detail than your dismissal justifies.

Sorry, I didn't explicitly state the perspective to read that statement from. 
I'm not saying the people participating here don't understand the ramifications 
which have been brought up (which I have read top-to-bottom). My point is 
people who are **not** reading this thread may be surprised if they try this 
(i.e. users out in the wild which was the perspective I meant to convey), but 
**if** they are brought to understand the complexity required to make their 
assumption work then I would hope they would understand why things work the way 
they do.

> Let's start with the minimal change we have suggested: that two views 
> should be considered equal if they both belong to the same dict.
> assert d.values() == d.values()
> Currently that assertion fails. Should it? Putting aside the convenience 
> of "do nothing, just inherit the object.__eq__ behaviour" do you think 
> that the current behaviour is correct?

Yes I do if we aren't going to make this work regardless of actual dict objects 
because if you don't make this work for `d1.values() == d2.values()` then I 
think that would make `d.values() == d.values()` more surprising as to why it 
works in one case where the values were all the same but not in another.

> (By correct I mean in the technical sense that if we were writing a 
> functional spec for views, we would actively desire two views of the 
> same dict to be unequal.)
> > To me a doc update for dict.values() stating that the
> > iterator can't 
> > be compared and a brief mention as to why would be the best solution 
> > for this.
> > We're not talking about comparing iterators. We're talking about 
> comparing views into a dict. That's a difference that makes all the 
> difference.

You're correct that I misspoke, but I personally still think a doc change is 
the best solution.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/K3SYX4DER3WAOWGQ4SPKCKXSXLXTIVAQ/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
Eric V. Smith wrote:
>That makes things worse. Now the comparison is always true in a boolean 
>context. And presumably you'd want __ne__ to also return >NotImplemented, 
>so then both __eq__ and __ne__ would be true, since >bool(NotImplemented) 
>is True.

Eric V Smith wrote:
7/25/2019 6:00 AM, Eric V. Smith wrote:
>I might have to take that back. I hadn't factored in what the == and != 
>machinery does, beyond calling __eq__ or __ne__.

Based on the behavior in this example class, it looks like this would still 
function appropriately, despite the value of bool(NotImplemented):

>>>class A:
   def __eq__(self, other):
   return NotImplemented
>>>a = A()
>>>b = A()
>>> a == b
False
>>> a != b
True

As you said, I believe it has to do with the underlying behavior of __eq__ and 
__ne__. However, this does somewhat lead to the same surface level issue of a 
False ultimately being returned. The NotImplemented makes the intention a bit 
more obvious if someone were to look at the __eq__ method for dict.values(), 
but otherwise it might still be the same issue. I'm somewhat curious as to why 
`a == b` doesn't directly return NotImplemented instead of False. Perhaps the 
underlying behavior makes it a pain to return anything other than True, False, 
or None (that's purely speculation on my part, I haven't looked further into 
it).
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/HTFXIN7L2UBEJ26AY2BTF5FEYA7MVUEX/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
Brett Cannon wrote:
> You're correct that I misspoke, but I personally still think a doc change
> is the best solution.

I would agree that a doc change should occur if it is decided that the current 
behavior is appropriate, but I would like to mention that in the current 
[documentation for 
`object.__eq__()`](https://docs.python.org/3/reference/datamodel.html#object.__eq__),
 it states: "A rich comparison method may return the singleton `NotImplemented` 
if it does not implement the operation for a given pair of arguments". 

Wouldn't returning `NotImplemented` be far more explicit to the user, in terms 
to directly telling them that the equality assessment between two dictionary 
views is not implemented? In general, I find this to be far more informative 
than simply returning False. At a surface level, users may assume that False 
would imply that there was an actual assessment of equality being performed. 

This may not be an established precedent for other similar equality 
assessments, but I don't think the `NotImplemented` constant is utilized as 
much as it could be. It seems to be particularly well suited for addressing 
this situation.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XHIXFB3BFOKQTWGUBUE5AJWHWAXXIGRD/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Serhiy Storchaka

25.07.19 22:05, Kyle Stanley пише:

I would agree that a doc change should occur if it is decided that the current behavior 
is appropriate, but I would like to mention that in the current [documentation for 
`object.__eq__()`](https://docs.python.org/3/reference/datamodel.html#object.__eq__), it 
states: "A rich comparison method may return the singleton `NotImplemented` if it 
does not implement the operation for a given pair of arguments".

Wouldn't returning `NotImplemented` be far more explicit to the user, in terms 
to directly telling them that the equality assessment between two dictionary 
views is not implemented? In general, I find this to be far more informative 
than simply returning False. At a surface level, users may assume that False 
would imply that there was an actual assessment of equality being performed.

This may not be an established precedent for other similar equality 
assessments, but I don't think the `NotImplemented` constant is utilized as 
much as it could be. It seems to be particularly well suited for addressing 
this situation.


NotImplemented is returned by the `__eq__` method, but the `==` operator 
returns False. Do not confuse them.


  >>> {}.values().__eq__({}.values())
  NotImplemented
  >>> {}.values() == {}.values()
  False

Actually, the `==` operator cannot return NotImplemented.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JLSKYYX5SU6VLNEVGVITUDCI3NRWALFS/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Terry Reedy

On 7/25/2019 2:46 PM, Brett Cannon wrote:


You're correct that I misspoke, but I personally still think a doc change is 
the best solution.


Given the absence of a consensus on when values() views should be 
considered equal, I strongly agree.  I strongly oppose raising an exception.


--
Terry Jan Reedy
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XA3PLUL5JQZGQK7MK7YCWZZMDUWGWP4H/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
Serhiy Storchaka wrote:
> Actually, the == operator cannot return NotImplemented.

Thanks for the clarification. What is the reason for this limitation and is it 
only possible for the `==` operator to return one of `None`, `False`, or 
`True`? It seems like it would be useful for it to be able to return 
`NotImplemented` in situations such as this.

Also, I think that I may have had some misconceptions with regards to the 
relationship between the `__eq__()` method and the `==` operator. I know they 
are not the same, but isn't the result of the `==` operator based on a 
transformation of the result from `__eq__()`?

As far as I can tell, the equality of two dictionary views are assessing used 
[`PyObject 
dictrich_compare`](https://github.com/python/cpython/blob/544fa15ea1b7b73068319bdb217b684e2fd7bacc/Objects/dictobject.c#L4040).
 Wouldn't it be possible to perform a conditional check if the view on the left 
side of the comparison is a values view and if so, use 
`Py_RETURN_NOTIMPLEMENTED`?

Apologies if I'm completely off base here, my experience and understanding of 
the underlying C-API is quite limited. I've been programming with Python for 
quite some time, but I only started learning the C-API once I became interested 
in contributing to CPython.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/72XO7ZWL6XZLQGDSHFSBENBHK5OG7HD4/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
Terry Reedy wrote:
> Given the absence of a consensus on when values() views should be 
> considered equal, I strongly agree.  I strongly oppose raising an exception.

I am with you regarding the strong opposition regarding the raising of an 
exception. I don't think that the `==` operator should raise an exception, 
doing so is excessively obstructive to the user.

I'm not certain that returning `False` is the best behavior, but based on what 
I've gathered from the discussion so far there has been nothing suggested that 
would be a viable alternative. I had initially proposed returning 
`NotImplemented`, but upon further assessment, that would still end up 
returning `False` when using the `==` operator. As a result, leaving it as is 
and addressing the behavior in the docs seems to be the most appropriate 
solution.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JAEML64F62M7ZB3U656CBE4YXQRU74QF/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Eric V. Smith



On 7/25/2019 4:19 PM, Kyle Stanley wrote:

Serhiy Storchaka wrote:

Actually, the == operator cannot return NotImplemented.


Thanks for the clarification. What is the reason for this limitation and is it 
only possible for the `==` operator to return one of `None`, `False`, or 
`True`? It seems like it would be useful for it to be able to return 
`NotImplemented` in situations such as this.


Because no one is testing for it. And just using it in a boolean context 
will return True.



Also, I think that I may have had some misconceptions with regards to the 
relationship between the `__eq__()` method and the `==` operator. I know they 
are not the same, but isn't the result of the `==` operator based on a 
transformation of the result from `__eq__()`?


"Based on", yes. If all of the options return NotImplemented, it falls 
back on identity comparison. I can't find this in the Python 3 docs, but 
it's no doubt somewhere.


Eric
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/LLE35RZQF3WMLJMMIIREUGJNMIVQBN3P/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Serhiy Storchaka

25.07.19 23:19, Kyle Stanley пише:

Serhiy Storchaka wrote:

Actually, the == operator cannot return NotImplemented.


Thanks for the clarification. What is the reason for this limitation and is it 
only possible for the `==` operator to return one of `None`, `False`, or `True`?


The `==` operator can return any value except NotImplemented. But all 
implementations in the stdlib return only booleans. NumPy is the one 
famous exception.



It seems like it would be useful for it to be able to return `NotImplemented` 
in situations such as this.


It is the purpose of NotImplemented. It signals "ignore me, use other 
way to evaluate a result".



Also, I think that I may have had some misconceptions with regards to the 
relationship between the `__eq__()` method and the `==` operator. I know they 
are not the same, but isn't the result of the `==` operator based on a 
transformation of the result from `__eq__()`?


Yes, it is. And NotImplemented means that the result of `__eq__()` (or 
other dunder methods) should be ignored.



As far as I can tell, the equality of two dictionary views are assessing used 
[`PyObject 
dictrich_compare`](https://github.com/python/cpython/blob/544fa15ea1b7b73068319bdb217b684e2fd7bacc/Objects/dictobject.c#L4040).
 Wouldn't it be possible to perform a conditional check if the view on the left 
side of the comparison is a values view and if so, use 
`Py_RETURN_NOTIMPLEMENTED`?


How does it differ from the default implementation (`object.__eq__`)?
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/RDHMG6SD7B3WTVZDBSB2LQ347YA2X753/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Greg Ewing

David Mertz wrote:
This feels similar to NumPy arrays, that also will not compare for 
equality in bare form.


Not quite the same -- comparing numpy arrays doesn't raise an exception,
it returns an array of booleans. What raises an exception is trying to
use the resulting array in a boolean context. But it is an example of
something raising an exception that one would normally expect to
always succeed.

In the case of dict.values() == dict.values(), raising an exception is
probably the least bad thing. Yes, it can lead to code blowing up
unexpectedly, but I think it's better than having code appear to
work while doing something subtly different from what you wanted.

--
Greg
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/723CHZBH4ZBKQJOOPXFFX3HYSPDBPDPR/


[Python-Dev] Fwd: Re: Comparing dict.values()

2019-07-25 Thread David Mertz
On Thu, Jul 25, 2019 at 4:35 AM Petr Viktorin  wrote:

> It's not the equality operator that errors: `==` means element-wise
> comparison in Numpy. The error would come from a conversion of the array
> to bool:
>
>  >>> numpy.array([1, 2, 3]) == numpy.array([1, 3, 4])
> array([ True, False, False])
>
>  >>> if numpy.array([ True, False, False]):
> ... print('Same!')
> ...
> Traceback (most recent call last):
>File "", line 1, in 
> ValueError: The truth value of an array with more than one element is
> ambiguous. Use a.any() or a.all()
>

This is true of course.  I was being overly concise, but `arr1 == arr2`
does not itself (currently) raise any exception.  It's only `if arr1==arr2`
that does.

But what NumPy does is return a "special" object that has some methods to
convert it into a boolean in different ways.  We COULD do that with
`d1.values() == d2.values()` in principle.  This "DictValuesComparison"
object could have methods like `.equal_as_set()` and `.equal_as_list()`.
However, that's a lot of machinery for very little gain.

In contrast, a NumPy boolean array is useful for lots of purposes, and it
is something we want independently to have around.  Mostly it's a great way
of indexing into another list of numeric elements.  But it also can be used
in some less common, but not uncommon ways.  A hypothetical
DictValuesComparison object would have nearly no use other than avoiding
wrapping d.values() in list(), which we can already do fine.  Sure, maybe
that rare case could be made a little faster with this custom machinery,
but it doesn't feel worthwhile to me.

Therefore, I think the exception with guidance in the message should happen
at actual equality (or inequality) comparison time, not when casting to a
boolean context.

Numpy currently returns False when `==` “doesn't make sense”, but
> apparently has plans to change that:
>
>  >>> numpy.array([1, 2, 3]) == numpy.array([1, 2])
> __main__:1: DeprecationWarning: elementwise comparison failed; this will
> raise an error in the future.
> False
>
>  >>> numpy.array([1, 2, 3]) == numpy.array(['a', 'b'])
> __main__:1: FutureWarning: elementwise comparison failed; returning
> scalar instead, but in the future will perform elementwise comparison
> False
>

This is very interesting! I did not know about this planned change.  That
NumPy will start raising exceptions on equality comparison adds a little
bit of support for my suggestion, I think.


> > So, a helpful error message including something like "Cannot compare
> > dict.values directly, consider converting to sets / lists / sorted
> > lists before comparing" ?
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/JBUS6FKXYUG4RTY2B6BUUO2DYNJT774Y/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Ivan Pozdeev via Python-Dev

On 23.07.2019 23:59, Kristian Klette wrote:


Hi!

During the sprints after EuroPython, I made an attempt at adding support for
comparing the results from `.values()` of two dicts.

Currently the following works as expected:

```
d = {'a': 1234}

d.keys() == d.keys()
d.items() == d.items()
```

but `d.values() == d.values()` does not return the expected
results. It always returns `False`. The symmetry is a bit off.

In the bug trackers[0] and the Github PR[1], I was asked
to raise the issue on the python-dev mailing list to find
a consensus on what comparing `.values()` should do.

I'd argue that Python should compare the values as expected here,
or if we don't want to encourage that behaviour, maybe we should
consider raising an exception.
Returning just `False` seems a bit misleading.

What are your thoughts on the issue?

Since a hash table is an unordered container and keys(), items() and values() are iterators over it, *I would expect the results of any of 
the comparisons to be undefined.*


While Python 3 dicts preserve order, it's _insertion_ order, so there's no guarantee that two equal dicts will iterate over the items in the 
same order.


*Comparing the sequences that iterators produce goes beyond the job of iterators* (i.e. requires iterating from start to finish under the 
hood and constructing temporary containers), so it shouldn't be a part of their functionality.
The implemented comparisons were specifically intended as convenience methods that go beyond the job of an iterator AFAICS but they fell 
short since in the case of `values()`, the task turned out to have too much computational complexity.


So *the comparion logic, if kept at all, should be reduced to comparing things that are intrinsic to iterators themselves:* whether they 
point to the same object and have the same internal state.
If someone needs to specifically compare the resulting sequences, they should use separate logic dedicated to comparing sequences -- with 
the associated quadratic complexity et al if then need to compare regardless or order. *The current logic encourages using iterators for 
things they aren't designed for so it's actively confusing and harmful.*



[0]: https://bugs.python.org/issue37585
[1]: https://github.com/python/cpython/pull/14737
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/R2MPDTTMJXAF54SICFSAWPPCCEWAJ7WF/


--
Regards,
Ivan

___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/QWOL2YGLSDLCTBNXC3GUSINUB2E5ODEU/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Random832
On Fri, Jul 26, 2019, at 00:22, Ivan Pozdeev via Python-Dev wrote:
> Since a hash table is an unordered container and keys(), items() and 
> values() are iterators over it, *I would expect the results of any of 
> the comparisons to be undefined.*

keys, items, and values are not iterators. They are view objects, and keys and 
items implement the entire set API (in the same sense that range implements the 
entire sequence API). Values is the odd one out in that it can contain multiple 
instances of each object, so it can't really be considered as a set.

Items also sometimes contains unhashable types, and some methods simply fail in 
that case. I suggest that this precedent provides a way forward - implement the 
entire intuitive "contains the same amount of each value" algorithm [more or 
less Counter(obj1) == Counter(obj2)], and have this fail naturally, throwing 
e.g. an exception "TypeError: unhashable type: 'list'" if any of the values are 
unhashable in the same way that trying to perform certain set operations on an 
items view does.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/UCW7SGSZPY2TNXYR2W7AB7NKAVTULZVT/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Inada Naoki
On Fri, Jul 26, 2019 at 2:03 PM Random832  wrote:
>
>
> Items also sometimes contains unhashable types, and some methods simply fail 
> in that case. I suggest that this precedent provides a way forward - 
> implement the entire intuitive "contains the same amount of each value" 
> algorithm [more or less Counter(obj1) == Counter(obj2)], and have this fail 
> naturally, throwing e.g. an exception "TypeError: unhashable type: 'list'" if 
> any of the values are unhashable in the same way that trying to perform 
> certain set operations on an items view does.

-1.  What is the motivation of this?
In this case, I don't think "I found missing parts so I want to
implement it for consistency"
is not enough reason to implement it.

I want a real-world application which requires it.
Without a strong use case, I think the discussion is just wasting time.

Regards,
-- 
Inada Naoki  
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/CZ3K6BZ3AAWABO4456YP6BYFMSXZVHAM/


[Python-Dev] Re: Comparing dict.values()

2019-07-25 Thread Kyle Stanley
> I want a real-world application which requires it.
> Without a strong use case, I think the discussion is just wasting time.

I would have to agree. Initially I was in support of changing the behavior, but 
upon reading the responses of several core developers and further 
consideration, the most appropriate course of action seems to be updating the 
docs. I have not seen any relevant applications where it would be useful to 
compare the values view between dictionaries, but I agree that the behavior of 
returning `False` might be confusing without any mention of it.

I [opened a PR](https://github.com/python/cpython/pull/14954) which mentions 
this behavior in the relevant documentation, but further explanation of why 
this occurs might be appropriate. I'm not certain as to whether or not further 
explanation is needed in this situation though.
___
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/D6XWQDTNQWXFD5ZKOSM3RTBZEFBXN6KM/