[Python-Dev] Re: Comparing dict.values()
On Tue, Jul 23, 2019 at 10:02:34PM -0400, Terry Reedy wrote: [...] > If one has not learned the default meaning of '==' in Python. Perhaps > this should be given more emphasis in beginner courses. "What does it > mean for two object to be 'equal'?" It is not a trivial question. No, it is not trivial, but the default meaning of equality in Python does not match the common idea that two things are equal if they are the same, equivalent, interchangeable, etc. By default, no two objects are ever equal, even if their values are equal. Equality only holds between an object and itself. (In fairness, it is hard to think of another, more useful, definition of equality suitable as the default.) In any case, the default semantics of equality inherited from object may explain the current behaviour, but that doesn't mean that the current behaviour is useful. When it is meaningful to say that "the value of these two distinct objects are equal", that is a strong hint that equality ought to be based on the value, rather than the identity, of the objects. [...] > Makes sense, up to here. I'm glad to hear it, because I think that's a strong invariate: if the items are equal, so should the values be equal. Beyond that, I'm not certain what is the right behaviour. > > # Fall back on value by value comparison? > > return list(self) == list(other) > > This seems wrong. Creating two lists raises the cost and the comparison > will depend on insertion order. You're probably right. I did say that this was potentially expensive. We should be able to avoid the needless creation of two lists: return all(x==y for x, y in zip(self, other)) but that still leaves the insertion order problem. How does this seem to you? Two dict.values objects are equal if: - they are in fact the same object (identity test on the views); - they are both views of the same dict (identity test on the dicts); - they are views of distinct, but equal, dicts; - or there is a 1:1 correspondence between values (possibly not unique) in the two views. The first three tests should be straight-forward. The last is likely be slow, but something like this ought to work: a = list(self) b = list(other) return len(a) == len(b) and all(a.count(x) == b.count(x) for x in a) Given that we cannot rely on the values being hashable or even sortable, I don't know how to make it more efficient in the general case. -- Steven ___ 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/JD74V5OSJDY7BHJWLXVD5NKQ5EP75EGL/
[Python-Dev] Re: Comparing dict.values()
Op 24 jul. 2019 om 02:27 heeft Steven D'Aprano het volgende geschreven: > But I can suggest at least one useful invariant. If a, b are two dicts: > >a.items() == b.items() > > ought to be equivalent to: > >(a.keys() == b.keys()) and (a.values() == b.values) I don’t think this invariant holds unless comparison is order dependent. {1:2, 3:4} and {1:4, 3:2} have the same keys and values, but not the same items. Ronald ___ 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/TRAL2TDEXGOWBSISTU3CCL6BCAXK4CVN/
[Python-Dev] Re: Comparing dict.values()
On 24/07/2019 10:31:46, Steven D'Aprano wrote: How does this seem to you? Two dict.values objects are equal if: - they are in fact the same object (identity test on the views); - they are both views of the same dict (identity test on the dicts); - they are views of distinct, but equal, dicts; Naive question: Is there a way (in Python) to get at the underlying dict from a dict.values object, or more generally from any dict view object? >>> dir({}.values()) ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', ' __init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', ' __repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] Rob Cliffe ___ 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/NZDVGFXMTUDW5ZSTAAMWFDLUEFLWGEGG/
[Python-Dev] Re: Comparing dict.values()
24.07.19 13:33, Rob Cliffe via Python-Dev пише: Naive question: Is there a way (in Python) to get at the underlying dict from a dict.values object, or more generally from any dict view object? No, there is not. As well as there is no way to get at the underlying list, tuple, dict from corresponding iterators. ___ 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/GQS5KVH36SHGTIRQZ63IGNCTZ6KESQXR/
[Python-Dev] Re: Comparing dict.values()
On Tue, 23 Jul 2019 23:44:35 +0100 MRAB wrote: > > However, when comparing the values you have a problem: you have 2 > collections of objects that might contain duplicates, might not be > hashable, and might not be sortable, so comparing them could be > inefficient, and you can't refer back to their keys like in the case of > comparing the items as above because the 2 dicts might have different > keys. Unless someone can come up with an efficient solution, I'd > probably go with raising an exception. Equality comparisons should never raise. 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/KNYYAVFME5ADN4UKMEW2TNHHZ4BGPSXG/
[Python-Dev] Re: What is a public API?
Barry Warsaw wrote: > On Jul 23, 2019, at 12:02, Steve Dower steve.do...@python.org wrote: > > Even if the performance impact is zero, commits that > > span the entire codebase for not-very-impactful changes have a negative > > impact on > > readability (for example, someone will suddenly become responsible for > > every single module > > as far as some blame tools are concerned - including github's suggested > > reviewers). I'm > > inclined to think this one would be primarily negative. > > If we were to adopt @public, its inclusion in the stdlib would follow the > precedence we already have for non-functional changes (e.g. whitespace, code > cleanup, > etc.). It definitely shouldn’t be done willy nilly but if the opportunity > arises, e.g. > because someone is already fixing bugs or modernizing a module, then it would > be fair game > to add @public decorators. Of course, you can’t do that if it’s not > available. :) > > We already maintain separate documentation from the > > source code, and this is the canonical reference for what is public or not. > > Until we make > > a new policy for __all__ to be the canonical reference, touching every file > > to use it is > > premature (let alone adding a builtin). > > Agreed, sort of. We’ve had lots of cases of grey areas though, where the > documentation doesn’t match the source. The question always becomes whether > the source or > the documentation is the source of truth. For any individual case, we don’t > always come > down on the same side of that question. > > So I apologise for mentioning that people care about > > import performance. Let's ignore them/that issue for now and worry instead > > about making > > sure people (including us!) know what the canonical reference for > > public/internal is. > > +1 Since this is for the stdlib, then PEP 8 would be the place to spell out how to denote public/private appropriately. ___ 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/Z7JMM7BB2YDP4FPU4WSLASCNQG2TXWR4/
[Python-Dev] Re: Comparing dict.values()
Serhiy Storchaka wrote: > 23.07.19 23:59, Kristian Klette пише: > > 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. > > Is it expected to you that iter(d) == iter(d) returns False? > By default the equality operator returns True when and only when > operands are identical. It is expected. Some objects (like numbers or > strings) can override the default behavior and implement different rules > for equality. > > 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 the rule for equality do you propose? What is the use case for it? > If you want to compare dict value views as ordered sequences, it can be > surprised that d1.values() != d2.values() when d1 == d2. It will > be > inconsistent with orderless comparison of keys() and items(). If > you > want to compare them as unordered sequences, the computation complexity > of the operation will be quadratic. > Note also, that while in Python 2 always d.values() == d.values(), it > is possible that d1.keys() != d2.keys() and d1.values() != > d2.values() when d1 == d2. Python 3 is more consistent. 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. 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. 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. ___ 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/PIFGKWEXP2LFEPCJJLVJAXIL3YCKVYCT/
[Python-Dev] Re: Comparing dict.values()
On 7/24/2019 1:30 PM, Brett Cannon wrote: Serhiy Storchaka wrote: o you propose? What is the use case for it? If you want to compare dict value views as ordered sequences, it can be surprised that d1.values() != d2.values() when d1 == d2. It will be inconsistent with orderless comparison of keys() and items(). If you want to compare them as unordered sequences, the computation complexity of the operation will be quadratic. Note also, that while in Python 2 always d.values() == d.values(), it is possible that d1.keys() != d2.keys() and d1.values() != d2.values() when d1 == d2. Python 3 is more consistent. 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. 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. 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. (I hope my quoting is correct.) I agree with Brett: let's just document this and not make any code changes. If someone really has a use case, which I haven't seen, then they can write their own comparison using constraints specific to their data: perhaps their values are hashable, for example. 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/C774AG3OQRG6XCZ4JKVP6UYDX6DELMQR/
[Python-Dev] Re: Comparing dict.values()
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. 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*? (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. -- Steven ___ 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/UPFBDHOHFSFLDF5KO3QZE6RH3C2GXE6B/
[Python-Dev] Re: Comparing dict.values()
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. -- 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/WR2JGENQBL3EQ6ZUUFF2BPMMFTFDEH3R/
[Python-Dev] Re: Comparing dict.values()
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. 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. This feels similar to NumPy arrays, that also will not compare for equality in bare form. But they offer .any(), and .all() and other means of expressing the comparison you actually want in a situation. On Wed, Jul 24, 2019, 6:32 PM Greg Ewing wrote: > 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. > > -- > 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/WR2JGENQBL3EQ6ZUUFF2BPMMFTFDEH3R/ > ___ 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/ROEAXSGAQOAOCTI7WL57FO23DDXSPN4E/
[Python-Dev] Re: Comparing dict.values()
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] Re: Comparing dict.values()
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: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all(). On Wed, Jul 24, 2019, 8:06 PM Rob Cliffe via Python-Dev < 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] Re: Comparing dict.values()
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 ). On 25/07/2019 00:49:56, Rob Cliffe via Python-Dev 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/ --- This email has been checked for viruses by AVG. https://www.avg.com ___ 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/5K4EP5AKR5XPGJ5657RCHRTS6QVSJVWE/