Title: Behavior of generator expressions doesn't match the docs when passed a non-iterable · Issue #143493 · python/cpython · GitHub
Open Graph Title: Behavior of generator expressions doesn't match the docs when passed a non-iterable · Issue #143493 · python/cpython
X Title: Behavior of generator expressions doesn't match the docs when passed a non-iterable · Issue #143493 · python/cpython
Description: Bug report Bug description: >>> def f(s): ... return (x for x in s) ... >>> f(1)
Open Graph Description: Bug report Bug description: >>> def f(s): ... return (x for x in s) ... >>> f(1)
X Description: Bug report Bug description: >>> def f(s): ... return (x for x in s) ... >>> f(1) <generator object f.<locals>.<genexpr> at 0xe8529f655c70> According to the docs ...
Opengraph URL: https://github.com/python/cpython/issues/143493
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Behavior of generator expressions doesn't match the docs when passed a non-iterable","articleBody":"# Bug report\n\n### Bug description:\n\n```python\n\u003e\u003e\u003e def f(s):\n... return (x for x in s)\n... \n\u003e\u003e\u003e f(1)\n\u003cgenerator object f.\u003clocals\u003e.\u003cgenexpr\u003e at 0xe8529f655c70\u003e\n```\n\nAccording to the docs (and in earlier versions) the correct behavior is:\n```\n\u003e\u003e\u003e def f(s):\n... return (x for x in s)\n... \n\u003e\u003e\u003e f(1)\nTypeError: 'int' object is not iterable\n```\n\nThe current behavior on main is arguably more logical as it is consistent with generators, but Hyrum's law dictates we need to be backwards compatible.\n\nhttps://docs.python.org/3/reference/expressions.html#generator-expressions\n\nThis issue has a bit of history.\nTo fix https://github.com/python/cpython/issues/125038 we moved the `GET_ITER` instruction into the generator body. This broke stuff, so we added a supposedly redundant `GET_ITER` to the callsite, but that also caused problems https://github.com/python/cpython/issues/127682.\nEventually, for 3.14 we added an additional check in `FOR_ITER` that the iterator is indeed an iterator.\nThis adds a little bit of unnecessary overhead and is an obstacle to optimization.\n\n\nOn main, we use \"virtual iterators\" and have kept the `GET_ITER` in the body of the generator. This is efficient and optimizes nicely, but doesn't conform to the docs.\n\nWe can keep both the nice performance and conform to the docs, by keeping the `GET_ITER` in the generator function, but moving it into generator creation and out of the generator body.\nInstead of:\n```\nRETURN_GENERATOR\n...\nLOAD__FAST 0\nGET_ITER\n```\nwe have:\n```\nLOAD_FAST 0\nGET_ITER\nRETURN_GENERATOR\n...\n```\n\n\n\n\n### CPython versions tested on:\n\nCPython main branch\n\n### Operating systems tested on:\n\n_No response_\n\n\u003c!-- gh-linked-prs --\u003e\n### Linked PRs\n* gh-143569\n\u003c!-- /gh-linked-prs --\u003e\n","author":{"url":"https://github.com/markshannon","@type":"Person","name":"markshannon"},"datePublished":"2026-01-06T19:42:16.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":3},"url":"https://github.com/143493/cpython/issues/143493"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:9406a1d2-9dcc-9458-3994-5a29022c6d23 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | EB1C:374780:29436F2:3621134:696B26D4 |
| html-safe-nonce | abfcbcba7a5b2272cbd992a8b80f41462c85caec380010c657a54ecff8b3c778 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQjFDOjM3NDc4MDoyOTQzNkYyOjM2MjExMzQ6Njk2QjI2RDQiLCJ2aXNpdG9yX2lkIjoiODgxNzE0ODkzNzkzNjUxMjcyNCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | d97271ac8a03d1f9bcc7548640e5e1c124eed2de038870b175a184fca20ba3ea |
| hovercard-subject-tag | issue:3786301522 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/143493/issue_layout |
| twitter:image | https://opengraph.githubassets.com/547c38c87b6bf19ad28bdd66fd192dadd2fe1db0eaa0da8b11e5754e5f31d14d/python/cpython/issues/143493 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/547c38c87b6bf19ad28bdd66fd192dadd2fe1db0eaa0da8b11e5754e5f31d14d/python/cpython/issues/143493 |
| og:image:alt | Bug report Bug description: >>> def f(s): ... return (x for x in s) ... >>> f(1) |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | markshannon |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f99f7c1d70f01da5b93e5ca90303359738944d8ab470e396496262c66e60b8d |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 82560a55c6b2054555076f46e683151ee28a19bc |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width