Skip to content

Fix evaluation order of keys/values in dict comprehensions #73838

Closed

Description

@DimitrisJim
BPO 29652
Nosy @rhettinger, @ncoghlan, @Janzert, @zhangyangyu, @DimitrisJim

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2019-09-17.23:36:16.137>
created_at = <Date 2017-02-25.19:54:43.014>
labels = ['interpreter-core', 'type-bug', '3.8']
title = 'Fix evaluation order of keys/values in dict comprehensions'
updated_at = <Date 2019-09-17.23:36:16.137>
user = 'https://github.com/DimitrisJim'

bugs.python.org fields:

activity = <Date 2019-09-17.23:36:16.137>
actor = 'brett.cannon'
assignee = 'none'
closed = True
closed_date = <Date 2019-09-17.23:36:16.137>
closer = 'brett.cannon'
components = ['Interpreter Core']
creation = <Date 2017-02-25.19:54:43.014>
creator = 'Jim Fasarakis-Hilliard'
dependencies = []
files = []
hgrepos = []
issue_num = 29652
keywords = []
message_count = 5.0
messages = ['288578', '288623', '315832', '315874', '351088']
nosy_count = 6.0
nosy_names = ['rhettinger', 'ncoghlan', 'janzert', 'xiang.zhang', 'Jim Fasarakis-Hilliard', 'EvKounis']
pr_nums = []
priority = 'normal'
resolution = 'fixed'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue29652'
versions = ['Python 3.8']

Activity

  1. DimitrisJim commented on Feb 25, 2017

    DimitrisJimmannequin
    MannequinAuthor

    Reported from [1] and similar to bpo-11205

    Currently the evaluation order for keys and values in a dictionary comprehension follows that of assignments. The values get evaluated first and then the keys:

        def printer(v):
            print(v, end=' ')
            return v
    
        d = {printer(i): printer(j) for i, j in [(1, 2), (3, 4)]}
        # 2 1 4 3

    This seems to conflict with the semantics as described in the Semantics section of PEP-274 [2] and according to my interpretation of the reference manual (I'd expect the evaluation to be similar to dict-displays).

    How should this be addressed? Fix the evaluation order or specify this edge case an "Implementation detail" in the reference manual?

    I already have a fix for this lying around (changes to compiler_sync_comprehension_generator, compiler_sync_comprehension_generator and a switch in MAP_ADD) and can make a pull request if required.

    I'm not sure if this is classified as a bug per-se so I only tagged Py3.7 for it.

    [1] http://stackoverflow.com/questions/42201932/order-of-operations-in-a-dictionary-comprehension
    [2] https://www.python.org/dev/peps/pep-0274/#semantics

  2. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    type-bugAn unexpected behavior, bug, or error
    on Feb 25, 2017
  3. rhettinger commented on Feb 27, 2017

    @rhettinger
    Contributor

    I think the current behavior is correct and desirable (as you say, it follows the order that would take place in an assignment, making it easy to roll-up existing for-loop code into a dict comprehension or to unroll and existing comprehension). Also, I think changing the behavior might risk introducing bugs into existing code that may have unconsciously relied on the existing order. My recommendation is to document the current value-first behavior.

    For the other issue, 11205, I agree with the discussion there that key-first-value-second makes more sense in the context of literals which are normally evaluated left-to-right.

  4. ncoghlan commented on Apr 27, 2018

    @ncoghlan
    Contributor

    The current discrepancy is odd when you compare it to the equivalent generator expression:

    {k:v for k, v in iterable}
    
    dict(((k, v) for k, v in iterable))
    

    It would never have occurred to me to expect the evaluation order to match a fully unrolled loop with a nested "d[k] = v" assignment, because the dict constructor doesn't work that way - it accepts an iterable of 2-tuples.

    PEP-274 also specifies the iterable-of-2-tuples interpretation (using a list comprehension as its baseline rather than a generator expression): https://www.python.org/dev/peps/pep-0274/#semantics

  5. added and removed on Apr 27, 2018
  6. Janzert commented on Apr 29, 2018

    Janzertmannequin
    Mannequin

    Just as a note so the email discussion isn't forever lost to the void.

    In an unrelated thread on python-dev recently there was a short discussion on this topic in which both Guido van Rossum[1] and Tim Peters[2] gave the opinion that this should change should probably be made.

    1: https://mail.python.org/pipermail/python-dev/2018-April/153122.html
    2: https://mail.python.org/pipermail/python-dev/2018-April/153134.html

  7. DimitrisJim commented on Sep 3, 2019

    DimitrisJimmannequin
    MannequinAuthor

    This was indeed changed as part of PEP-572. Should be closed as fixed.

  8. transferred this issue fromon Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.8 (EOL)end of lifeinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions