GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Walrus comprehension rebind checking behavior · Issue #87447 · python/cpython

Walrus comprehension rebind checking behavior #87447

New issue
Copy link
New issue
Copy link
Closed
Closed
Walrus comprehension rebind checking behavior#87447
Copy link
Labels
type-featureA feature request or enhancementA feature request or enhancement

Description

gousaiyang
mannequin
opened on Feb 21, 2021
Issue body actions
BPO 43281
Nosy @gvanrossum, @emilyemorehouse, @gousaiyang

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 = None
created_at = <Date 2021-02-21.01:20:04.826>
labels = ['type-bug', '3.8', '3.9', '3.10']
title = 'Walrus comprehension rebind checking behavior'
updated_at = <Date 2021-02-27.05:46:20.917>
user = 'https://github.com/gousaiyang'

bugs.python.org fields:

activity = <Date 2021-02-27.05:46:20.917>
actor = 'gvanrossum'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = []
creation = <Date 2021-02-21.01:20:04.826>
creator = 'gousaiyang'
dependencies = []
files = []
hgrepos = []
issue_num = 43281
keywords = []
message_count = 2.0
messages = ['387433', '387768']
nosy_count = 3.0
nosy_names = ['gvanrossum', 'emilyemorehouse', 'gousaiyang']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue43281'
versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

Linked PRs

  • gh-87447: Fix walrus comprehension rebind checking #100581

Activity

  1. gousaiyang commented on Feb 21, 2021

    @gousaiyang
    gousaiyangmannequin
    on Feb 21, 2021
    MannequinAuthor
    More actions

    # test

    PEP-572 disallows walrus use cases such as [(i := 1) for i in [1]], because for i implies that i is local to the comprehension but (i := 1) implies that i is "exported", which is a contradiction. However, I noticed the following behavior both in 3.8 and 3.9:

    >>> [(a := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'a'
    >>> [(b := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'b'
    >>> [(c := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'c'
    >>> [(d := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'd'
    >>> [(e := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'e'
    >>> [(f := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'f'
    >>> [(g := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'g'
    >>> [(h := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'h'
    >>> [(i := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <listcomp>
    TypeError: cannot unpack non-iterable int object

    Among all of these assignment expressions, only the assignment to i (attribute name) is allowed. However, in my understanding, only a and b should be disallowed for assignment. This comprehension example only creates two new variables, a and b, which are local to the comprehension. Assignment expressions assigning to c, d, e, f, g and h should be allowed. c and h are already in the outer scope. d, e, f and g are just names inside the expression in the subscript part. They are not "comprehension iteration variables" and not local to the comprehension.

    The same behavior is also observed when detecting inner loop variable rebinding outer loop assignment expression targets:

    >>> [i for i in range(5) if (j := 0) for k[j + 1] in range(5)]
      File "<stdin>", line 1
    SyntaxError: comprehension inner loop cannot rebind assignment expression target 'j'
  2. gousaiyang
    added
    3.8 (EOL)end of lifeend of life
    3.9 (EOL)end of lifeend of life
    3.10 (EOL)end of lifeend of life
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Feb 21, 2021
  3. gvanrossum commented on Feb 27, 2021

    @gvanrossum
    gvanrossum
    on Feb 27, 2021
    Member
    More actions

    I'd like Emily to have a look at that.

  4. ezio-melotti
    transferred this issue fromon Apr 10, 2022
  5. sobolevn
    added a commit that references this issue on Dec 28, 2022

    pythongh-87447: Fix walrus comprehension rebind checking

    4a9c194
  6. sobolevn commented on Dec 28, 2022

    @sobolevn
    sobolevn
    on Dec 28, 2022
    Member
    More actions

    I had some free time to learn more about symtable.c and fix this :)
    So, I hope my PR is in the right direction!

  7. hauntsaninja commented on Dec 29, 2022

    @hauntsaninja
    hauntsaninja
    on Dec 29, 2022
    Contributor
    More actions

    I think it probably needs a little more discussion whether this should be fixed.

    I found it useful to look at a slightly simpler example than the test case, like:

    index = 0
    a = [0, 0, 0]
    [(index := i) for i, a[index] in enumerate([9,8,7])]

    Arguments in favour of changing:

    • Like OP points out, the rationale in PEP 572 for outlawing these only applies to a and b; the scoping is clear for the other variables (so at least we'd have to invent new reasons to keep this outlawed)
    • I think it's a little surprising that one gets SyntaxError: assignment expression cannot rebind comprehension iteration variable 'index' from the above
    • It's seemingly a small change to fix in CPython
    • I could squint my eyes to believing there's some use case for it

    Arguments against changing:

    • Any comprehension that does this is going to be at least a little cursed. No concrete use case has been proposed
    • It'd maybe be a little weird that you could do [(a := [i]) for i, a[0] in enumerate([9,8,7])] but not be able to do [(a := i) for i, a in enumerate([9,8,7])]
    • There are stricter-than-strictly-necessary restrictions on assignment expressions in comprehensions that we're okay with, that I find more surprising than this (disallowing them entirely in the iterable)
    • Python 3.8 has been around for a couple years and this hasn't really come up. Changing this could necessitate changes in other Python implementations or linters

    Overall, I think I lean against, but I could be convinced otherwise!

  8. sobolevn commented on Dec 29, 2022

    @sobolevn
    sobolevn
    on Dec 29, 2022
    Member
    More actions

    My main argument to fix this is that error message does not show the reality:

    >>> [(h := 1) for a, (*b, c[d+e::f(g)], h.i) in [1]]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot rebind comprehension iteration variable 'h'

    But, h is not a comprehension iteration variable, h.i is.

    So, in my opinion it is clearly a bug. But, there are two ways of fixing it:

    1. Allow to rebind h if h.i is used, as in my PR
    2. Try changing the error message to something like assignment expression cannot rebind variable 'h' that is used in comprehension iteration expression (or whatever)
  9. gvanrossum commented on Dec 29, 2022

    @gvanrossum
    gvanrossum
    on Dec 29, 2022
    Member
    More actions

    I feel for the OP and I agree with several arguments in favor of this fix, given that it's a simple fix. Shantanu's arguments against feel pretty weak (probably intentionally so: "at least a little", "maybe a little").

    Maybe the other thing (disallowing named expressions in the iterable altogether) can be fixed in another PR?

  10. sobolevn commented on Dec 29, 2022

    @sobolevn
    sobolevn
    on Dec 29, 2022
    Member
    More actions

    Maybe the other thing (disallowing named expressions in the iterable altogether) can be fixed in another PR?

    Are you talking about forbidding := in [(h := 1) for a part? If I understand you correctly, this would be a breaking change, because even PEP 572 references this use-case: https://peps.python.org/pep-0572/#scope-of-the-target

    # Compute partial sums in a list comprehension
    total = 0
    partial_sums = [total := total + v for v in values]
    print("Total:", total)

    However, I probably just didn't get your idea :)

  11. gvanrossum commented on Dec 29, 2022

    @gvanrossum
    gvanrossum
    on Dec 29, 2022
    Member
    More actions

    I was talking about this from Shantanu:

    • There are stricter-than-strictly-necessary restrictions on assignment expressions in comprehensions that we're okay with, that I find more surprising than this (disallowing them entirely in the iterable)

    This is about things like:

    >>> [x for x in (a := range(3))]
      File "<stdin>", line 1
    SyntaxError: assignment expression cannot be used in a comprehension iterable expression
    >>> 
    Reacted by sobolevn
  12. emilyemorehouse
    added a commit that references this issue on Jan 8, 2023

    gh-87447: Fix walrus comprehension rebind checking (#100581)

    bc0a686
  13. emilyemorehouse
    added
    type-featureA feature request or enhancementA feature request or enhancement
    and removed
    3.8 (EOL)end of lifeend of life
    3.9 (EOL)end of lifeend of life
    3.10 (EOL)end of lifeend of life
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Jan 8, 2023
  14. emilyemorehouse commented on Jan 8, 2023

    @emilyemorehouse
    emilyemorehouse
    on Jan 8, 2023
    Member
    More actions

    Fixed in #100581

  15. emilyemorehouse
    closed this as completedon Jan 8, 2023
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

    type-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.