7123 lines
873 KiB
HTML
7123 lines
873 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<title>
|
||
What does the "yield" keyword do in Python? - Stack Overflow
|
||
</title>
|
||
<link rel="shortcut icon" href="https://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico?v=ec617d715196" />
|
||
<link rel="apple-touch-icon" href="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a" />
|
||
<link rel="image_src" href="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a" />
|
||
<link rel="search" type="application/opensearchdescription+xml" title="Stack Overflow" href="/opensearch.xml" />
|
||
<link rel="canonical" href="https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python" />
|
||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python" />
|
||
<meta property="og:site_name" content="Stack Overflow" />
|
||
<meta property="og:image" itemprop="image primaryImageOfPage" content="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon@2.png?v=73d79a89bded" />
|
||
<meta name="twitter:card" content="summary" />
|
||
<meta name="twitter:domain" content="stackoverflow.com" />
|
||
<meta name="twitter:title" property="og:title" itemprop="name" content="What does the "yield" keyword do in Python?" />
|
||
<meta name="twitter:description" property="og:description" itemprop="description" content="What is the use of the yield keyword in Python? What does it do? For example, I'm trying to understand this code1: def _get_child_candidates(self, distance, min_dist, max_dist): if self._leftch..." />
|
||
<script id="webpack-public-path" type="text/uri-list">
|
||
<![CDATA[
|
||
https://cdn.sstatic.net/
|
||
]]>
|
||
</script>
|
||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
|
||
<script defer="defer" src="https://cdn.sstatic.net/Js/third-party/npm/@stackoverflow/stacks/dist/js/stacks.min.js?v=facbc6b2f3b6"></script>
|
||
<script src="https://cdn.sstatic.net/Js/stub.en.js?v=0e3ada576039"></script>
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Shared/stacks.css?v=5ad0f45f4799" />
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/stackoverflow/primary.css?v=262abaa77efd" />
|
||
<link rel="alternate" type="application/atom+xml" title="Feed for question 'What does the "yield" keyword do in Python?'" href="/feeds/question/231767" />
|
||
<meta name="twitter:app:country" content="US" />
|
||
<meta name="twitter:app:name:iphone" content="Stack Exchange iOS" />
|
||
<meta name="twitter:app:id:iphone" content="871299723" />
|
||
<meta name="twitter:app:url:iphone" content="se-zaphod://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python" />
|
||
<meta name="twitter:app:name:ipad" content="Stack Exchange iOS" />
|
||
<meta name="twitter:app:id:ipad" content="871299723" />
|
||
<meta name="twitter:app:url:ipad" content="se-zaphod://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python" />
|
||
<meta name="twitter:app:name:googleplay" content="Stack Exchange Android" />
|
||
<meta name="twitter:app:url:googleplay" content="https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python" />
|
||
<meta name="twitter:app:id:googleplay" content="com.stackexchange.marvin" />
|
||
<script>
|
||
<![CDATA[
|
||
StackExchange.ready(function () {
|
||
|
||
StackExchange.using("snippets", function () {
|
||
StackExchange.snippets.initSnippetRenderer();
|
||
});
|
||
|
||
StackExchange.using("postValidation", function () {
|
||
StackExchange.postValidation.initOnBlurAndSubmit($('#post-form'), 2, 'answer');
|
||
});
|
||
|
||
|
||
StackExchange.question.init({showAnswerHelp:true,showTrendingSortLaunchPopover:false,showTrendingSortPostLaunchPopover:false,totalCommentCount:0,shownCommentCount:0,enableTables:true,questionId:231767});
|
||
|
||
styleCode();
|
||
|
||
StackExchange.realtime.subscribeToQuestion('1', '231767');
|
||
StackExchange.using("gps", function () { StackExchange.gps.trackOutboundClicks('#content', '.js-post-body'); });
|
||
|
||
|
||
});
|
||
]]>
|
||
</script>
|
||
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Shared/Channels/channels.css?v=d098999fc478" />
|
||
<script type="application/json" data-role="module-args" data-module-name="Shared/options.mod">
|
||
<![CDATA[
|
||
{"options":{"locale":"en","serverTime":1669282847,"routeName":"Questions/Show","stackAuthUrl":"https://stackauth.com","networkMetaHostname":"meta.stackexchange.com","site":{"name":"Stack Overflow","description":"Q\u0026A for professional and enthusiast programmers","isNoticesTabEnabled":true,"enableNewTagCreationWarning":true,"insertSpaceAfterNameTabCompletion":false,"id":1,"cookieDomain":".stackoverflow.com","childUrl":"https://meta.stackoverflow.com","negativeVoteScoreFloor":null,"enableSocialMediaInSharePopup":true,"protocol":"https"},"user":{"fkey":"c8f120bafcec1b4517505b02755fcebdb9c1cae6fe930e66fce90005c8a9a8a4","tid":"82c98d84-bddc-5338-80df-ee6791e089c1","rep":0,"isAnonymous":true,"isAnonymousNetworkWide":true},"events":{"postType":{"question":1},"postEditionSection":{"title":1,"body":2,"tags":3}},"svgIconPath":"https://cdn.sstatic.net/Img/stacks-icons","svgIconHash":"152dfe64472f"}}
|
||
]]>
|
||
</script>
|
||
<script type="application/json" data-role="module-args" data-module-name="Shared/settings.mod">
|
||
<![CDATA[
|
||
{"settings":{"userMessaging":{"showNewFeatureNotice":true},"tags":{},"subscriptions":{"defaultBasicMaxTrueUpSeats":250,"defaultFreemiumMaxTrueUpSeats":50,"defaultMaxTrueUpSeats":1000},"snippets":{"renderDomain":"stacksnippets.net","snippetsEnabled":true},"site":{"allowImageUploads":true,"enableImgurHttps":true,"enableUserHovercards":true,"forceHttpsImages":true,"stacksEditorPreviewEnabled":true,"styleCode":true},"questions":{"enableQuestionTitleLengthLiveWarning":true,"enableSavesFeature":true,"maxTitleSize":150,"questionTitleLengthStartLiveWarningChars":50},"intercom":{"appId":"inf0secd","hostBaseUrl":"https://stacksnippets.net"},"paths":{"jQueryUICSSPath":"https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/themes/smoothness/jquery-ui.css","jQueryUIJSPath":"https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.0/jquery-ui.min.js"},"monitoring":{"clientTimingsAbsoluteTimeout":30000,"clientTimingsDebounceTimeout":1000},"mentions":{"maxNumUsersInDropdown":50},"markdown":{"enableTables":true},"legal":{"oneTrustConfigId":"c3d9f1e3-55f3-4eba-b268-46cee4c6789c"},"flags":{"allowRetractingCommentFlags":true,"allowRetractingFlags":true},"elections":{"opaVoteResultsBaseUrl":"https://www.opavote.com/results/"},"comments":{},"accounts":{"currentPasswordRequiredForChangingStackIdPassword":true}}}
|
||
]]>
|
||
</script>
|
||
<script>
|
||
<![CDATA[
|
||
StackExchange.init();
|
||
]]>
|
||
</script>
|
||
<script>
|
||
<![CDATA[
|
||
StackExchange.using.setCacheBreakers({"Js/adops.en.js":"6da43f5e0a84","Js/ask.en.js":"","Js/begin-edit-event.en.js":"dd955babf04d","Js/copy-transpiled.en.js":"e7855bee94f2","Js/events.en.js":"","Js/explore-qlist.en.js":"2b1f34938b8b","Js/full-anon.en.js":"1dd7c4bcf6fa","Js/full.en.js":"887a26a55220","Js/highlightjs-loader.en.js":"a284064706b3","Js/inline-tag-editing.en.js":"629d801833ec","Js/keyboard-shortcuts.en.js":"a715495ee04f","Js/markdown-it-loader.en.js":"5818ef89ff9d","Js/moderator.en.js":"b08f5d20ce12","Js/postCollections-transpiled.en.js":"529276cfb7ae","Js/post-validation.en.js":"a49eba10a0e2","Js/question-editor.en.js":"","Js/review-v2-transpiled.en.js":"d5efdefd09e8","Js/revisions.en.js":"a86490719687","Js/stacks-editor.en.js":"198834eebc62","Js/tageditor.en.js":"825c9597ce2d","Js/tageditornew.en.js":"4340d4f2a34c","Js/tagsuggestions.en.js":"1bcff7d98f97","Js/unlimited-transpiled.en.js":"7ed67670b600","Js/wmd.en.js":"6a59bb1514a2","Js/snippet-javascript-codemirror.en.js":"73fce5cc7219"});
|
||
StackExchange.using("gps", function() {
|
||
StackExchange.gps.init(false);
|
||
});
|
||
]]>
|
||
</script><noscript id="noscript-css">
|
||
<style>
|
||
<![CDATA[
|
||
body,.s-topbar{margin-top:1.9em}
|
||
]]>
|
||
</style></noscript>
|
||
<script async="async" src="https://cdn.sstatic.net/Js/full-anon.en.js?v=1dd7c4bcf6fa"></script>
|
||
<script async="async" src="https://cdn.sstatic.net/Js/post-validation.en.js?v=a49eba10a0e2"></script>
|
||
<script async="async" src="https://cdn.sstatic.net/Js/highlightjs-loader.en.js?v=a284064706b3"></script>
|
||
<meta http-equiv="origin-trial" content="Az6AfRvI8mo7yiW5fLfj04W21t0ig6aMsGYpIqMTaX60H+b0DkO1uDr+7BrzMcimWzv/X7SXR8jI+uvbV0IJlwYAAACFeyJvcmlnaW4iOiJodHRwczovL2RvdWJsZWNsaWNrLm5ldDo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjgwNjUyNzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==" />
|
||
<meta http-equiv="origin-trial" content="A+USTya+tNvDPaxUgJooz+LaVk5hPoAxpLvSxjogX4Mk8awCTQ9iop6zJ9d5ldgU7WmHqBlnQB41LHHRFxoaBwoAAACLeyJvcmlnaW4iOiJodHRwczovL2dvb2dsZXN5bmRpY2F0aW9uLmNvbTo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjgwNjUyNzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==" />
|
||
<meta http-equiv="origin-trial" content="A7FovoGr67TUBYbnY+Z0IKoJbbmRmB8fCyirUGHavNDtD91CiGyHHSA2hDG9r9T3NjUKFi6egL3RbgTwhhcVDwUAAACLeyJvcmlnaW4iOiJodHRwczovL2dvb2dsZXRhZ3NlcnZpY2VzLmNvbTo0NDMiLCJmZWF0dXJlIjoiUHJpdmFjeVNhbmRib3hBZHNBUElzIiwiZXhwaXJ5IjoxNjgwNjUyNzk5LCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==" />
|
||
<script src="https://pagead2.googlesyndication.com/gpt/pubads_impl_2022111501.js" async="async"></script>
|
||
</head>
|
||
<body class="question-page unified-theme">
|
||
<div id="notify-container"></div>
|
||
<div id="custom-header"></div>
|
||
<header class="s-topbar ps-fixed t0 l0 js-top-bar">
|
||
<div class="s-topbar--container">
|
||
<a href="#" class="s-topbar--menu-btn js-left-sidebar-toggle" role="menuitem" aria-haspopup="true" aria-controls="left-sidebar" aria-expanded="false"></a>
|
||
<div class="topbar-dialog leftnav-dialog js-leftnav-dialog dno">
|
||
<div class="left-sidebar js-unpinned-left-sidebar" data-can-be="left-sidebar" data-is-here-when="sm"></div>
|
||
</div><a href="https://stackoverflow.com" class="s-topbar--logo js-gps-track" data-gps-track="top_nav.click({is_current:false, location:2, destination:8})"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /></a>
|
||
<ol class="s-navigation" role="presentation">
|
||
<li class="md:d-none">
|
||
<a href="https://stackoverflow.co/" class="s-navigation--item js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:7})" data-ga="["top navigation","about menu click",null,null,null]">About</a>
|
||
</li>
|
||
<li>
|
||
<a href="#" class="s-navigation--item js-gps-track js-products-menu" aria-controls="products-popover" data-controller="s-popover" data-action="s-popover#toggle" data-s-popover-placement="bottom" data-s-popover-toggle-class="is-selected" data-gps-track="top_nav.products.click({location:2, destination:1})" data-ga="["top navigation","products menu click",null,null,null]" aria-expanded="false">Products</a>
|
||
</li>
|
||
<li class="md:d-none">
|
||
<a href="/teams" class="s-navigation--item js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:7})" data-ga="["top navigation","learn more - teams",null,null,null]">For Teams</a>
|
||
</li>
|
||
</ol>
|
||
<div class="s-popover ws2 mtn2 p0" id="products-popover" role="menu" aria-hidden="true">
|
||
<div class="s-popover--arrow"></div>
|
||
<ol class="list-reset s-anchors s-anchors__inherit">
|
||
<li class="m6">
|
||
<a href="/questions" class="bar-sm p6 d-block h:bg-black-100 js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:2})" data-ga="["top navigation","public qa submenu click",null,null,null]"><span class="fs-body1 d-block">Stack Overflow</span> <span class="fs-caption d-block fc-light">Public questions & answers</span></a>
|
||
</li>
|
||
<li class="m6">
|
||
<a href="/teams" class="bar-sm p6 d-block h:bg-black-100 js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:3})" data-ga="["top navigation","teams submenu click",null,null,null]"><span class="fs-body1 d-block">Stack Overflow for Teams</span> <span class="fs-caption d-block fc-light">Where developers & technologists share private knowledge with coworkers</span></a>
|
||
</li>
|
||
<li class="m6">
|
||
<a href="https://stackoverflow.co/talent" class="bar-sm p6 d-block h:bg-black-100 js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:5})" data-ga="["top navigation","talent submenu click",null,null,null]"><span class="fs-body1 d-block">Talent</span> <span class="fs-caption d-block fc-light">Build your employer brand</span></a>
|
||
</li>
|
||
<li class="m6">
|
||
<a href="https://stackoverflow.co/advertising" class="bar-sm p6 d-block h:bg-black-100 js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:6})" data-ga="["top navigation","advertising submenu click",null,null,null]"><span class="fs-body1 d-block">Advertising</span> <span class="fs-caption d-block fc-light">Reach developers & technologists worldwide</span></a>
|
||
</li>
|
||
<li class="bg-black-025 bt bc-black-075 py6 px6 bbr-md">
|
||
<a href="https://stackoverflow.co/" class="fc-light d-block py6 px6 h:fc-black-800 js-gps-track" data-gps-track="top_nav.products.click({location:2, destination:7})" data-ga="["top navigation","about submenu click",null,null,null]">About the company</a>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<form id="search" role="search" action="/search" class="s-topbar--searchbar js-searchbar" autocomplete="off" name="search">
|
||
<div class="s-topbar--searchbar--input-group">
|
||
<input name="q" type="text" role="combobox" placeholder="Search…" value="" autocomplete="off" maxlength="240" class="s-input s-input__search js-search-field" aria-label="Search" aria-controls="top-search" data-controller="s-popover" data-action="focus->s-popover#show" data-s-popover-placement="bottom-start" aria-expanded="false" /> <svg aria-hidden="true" class="s-input-icon s-input-icon__search svg-icon iconSearch" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m18 16.5-5.14-5.18h-.35a7 7 0 1 0-1.19 1.19v.35L16.5 18l1.5-1.5ZM12 7A5 5 0 1 1 2 7a5 5 0 0 1 10 0Z"></path></svg>
|
||
<div class="s-popover p0 wmx100 wmn4 sm:wmn-initial js-top-search-popover" id="top-search" role="menu">
|
||
<div class="s-popover--arrow"></div>
|
||
<div class="js-spinner p24 d-flex ai-center jc-center d-none">
|
||
<div class="s-spinner s-spinner__sm fc-orange-400">
|
||
<div class="v-visible-sr">
|
||
Loading…
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-ac-results overflow-y-auto hmx3 d-none"></div>
|
||
<div class="js-search-hints" aria-describedby="Tips for searching"></div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
<nav class="h100 ml-auto overflow-x-auto pr12">
|
||
<ol class="s-topbar--content" role="menubar">
|
||
<li class="js-topbar-dialog-corral" role="presentation">
|
||
<div class="topbar-dialog siteSwitcher-dialog dno" role="menu">
|
||
<div class="header fw-wrap">
|
||
<h3 class="flex--item">
|
||
<a href="https://stackoverflow.com">current community</a>
|
||
</h3>
|
||
<div class="flex--item fl1">
|
||
<div class="ai-center d-flex jc-end">
|
||
<button class="js-close-button s-btn s-btn__muted p0 ml8 d-none sm:d-block" type="button" aria-label="Close"><svg aria-hidden="true" class="svg-icon iconClear" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M15 4.41 13.59 3 9 7.59 4.41 3 3 4.41 7.59 9 3 13.59 4.41 15 9 10.41 13.59 15 15 13.59 10.41 9 15 4.41Z"></path></svg></button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-content bg-powder-050 current-site-container">
|
||
<ul class="current-site">
|
||
<li class="d-flex">
|
||
<div class="fl1">
|
||
<a href="https://stackoverflow.com" class="current-site-link site-link js-gps-track d-flex gs8 gsx" data-id="1" data-gps-track="site_switcher.click({ item_type:3 })"><img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <span class="flex--item fl1">Stack Overflow</span></a>
|
||
</div>
|
||
<div class="related-links">
|
||
<a href="https://stackoverflow.com/help" class="js-gps-track" data-gps-track="site_switcher.click({ item_type:14 })">help</a> <a href="https://chat.stackoverflow.com/?tab=site&host=stackoverflow.com" class="js-gps-track" data-gps-track="site_switcher.click({ item_type:6 })">chat</a>
|
||
</div>
|
||
</li>
|
||
<li class="related-site d-flex">
|
||
<div class="L-shaped-icon-container"></div><a href="https://meta.stackoverflow.com" class="site-link js-gps-track d-flex gs8 gsx" data-id="552" data-gps-track="site.switch({ target_site:552, item_type:3 }),site_switcher.click({ item_type:4 })"><img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <span class="flex--item fl1">Meta Stack Overflow</span></a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="header" id="your-communities-header">
|
||
<h3>
|
||
your communities
|
||
</h3>
|
||
</div>
|
||
<div class="modal-content" id="your-communities-section">
|
||
<div class="call-to-login">
|
||
<a href="https://stackoverflow.com/users/signup?ssrc=site_switcher&returnurl=https%3a%2f%2fstackoverflow.com%2fquestions%2f231767%2fwhat-does-the-yield-keyword-do-in-python" class="login-link js-gps-track" data-gps-track="site_switcher.click({ item_type:10 })">Sign up</a> or <a href="https://stackoverflow.com/users/login?ssrc=site_switcher&returnurl=https%3a%2f%2fstackoverflow.com%2fquestions%2f231767%2fwhat-does-the-yield-keyword-do-in-python" class="login-link js-gps-track" data-gps-track="site_switcher.click({ item_type:11 })">log in</a> to customize your list.
|
||
</div>
|
||
</div>
|
||
<div class="header">
|
||
<h3>
|
||
<a href="https://stackexchange.com/sites">more stack exchange communities</a>
|
||
</h3><a href="https://stackoverflow.blog" class="float-right">company blog</a>
|
||
</div>
|
||
<div class="modal-content">
|
||
<div class="child-content"></div>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li role="none">
|
||
<button class="s-topbar--item s-btn s-btn__icon s-btn__muted d-none sm:d-inline-flex js-searchbar-trigger" role="menuitem" aria-label="Search" aria-haspopup="true" aria-controls="search" title="Click to show search"><svg aria-hidden="true" class="svg-icon iconSearch" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m18 16.5-5.14-5.18h-.35a7 7 0 1 0-1.19 1.19v.35L16.5 18l1.5-1.5ZM12 7A5 5 0 1 1 2 7a5 5 0 0 1 10 0Z"></path></svg></button>
|
||
</li>
|
||
<li role="none">
|
||
<a href="https://stackoverflow.com/users/login?ssrc=head&returnurl=https%3a%2f%2fstackoverflow.com%2fquestions%2f231767%2fwhat-does-the-yield-keyword-do-in-python" class="s-topbar--item s-topbar--item__unset s-btn s-btn__filled ws-nowrap js-gps-track" role="menuitem" rel="nofollow" data-gps-track="login.click" data-ga="["top navigation","login button click",null,null,null]">Log in</a>
|
||
</li>
|
||
<li role="none">
|
||
<a href="https://stackoverflow.com/users/signup?ssrc=head&returnurl=https%3a%2f%2fstackoverflow.com%2fquestions%2f231767%2fwhat-does-the-yield-keyword-do-in-python" class="s-topbar--item s-topbar--item__unset ml4 s-btn s-btn__primary ws-nowrap" role="menuitem" rel="nofollow" data-ga="["sign up","Sign Up Navigation","Header",null,null]">Sign up</a>
|
||
</li>
|
||
</ol>
|
||
</nav>
|
||
</div>
|
||
</header>
|
||
<script>
|
||
<![CDATA[
|
||
StackExchange.ready(function () { StackExchange.topbar.init(); });
|
||
StackExchange.scrollPadding.setPaddingTop(50, 10);
|
||
]]>
|
||
</script>
|
||
<div class="container">
|
||
<div id="left-sidebar" data-is-here-when="md lg" class="left-sidebar js-pinned-left-sidebar ps-relative">
|
||
<div class="left-sidebar--sticky-container js-sticky-leftnav">
|
||
<nav role="navigation">
|
||
<ol class="nav-links">
|
||
<li class="ps-relative" aria-current="false">
|
||
<a href="/" class="pl8 js-gps-track nav-links--link" data-gps-track="top_nav.click({is_current: false, location:2, destination:8})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never">
|
||
<div class="d-flex ai-center">
|
||
<div class="flex--item truncate">
|
||
Home
|
||
</div>
|
||
</div></a>
|
||
</li>
|
||
<li>
|
||
<ol class="nav-links">
|
||
<li class="fs-fine tt-uppercase ml8 mt16 mb4 fc-light">Public
|
||
</li>
|
||
<li class="ps-relative youarehere" aria-current="true">
|
||
<a id="nav-questions" href="/questions" class="pl8 js-gps-track nav-links--link -link__with-icon" data-gps-track="top_nav.click({is_current: true, location:2, destination:1})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never"><svg aria-hidden="true" class="svg-icon iconGlobe" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M9 1C4.64 1 1 4.64 1 9c0 4.36 3.64 8 8 8 4.36 0 8-3.64 8-8 0-4.36-3.64-8-8-8ZM8 15.32a6.46 6.46 0 0 1-4.3-2.74 6.46 6.46 0 0 1-.93-5.01L7 11.68v.8c0 .88.12 1.32 1 1.32v1.52Zm5.72-2c-.2-.66-1-1.32-1.72-1.32h-1v-2c0-.44-.56-1-1-1H6V7h1c.44 0 1-.56 1-1V5h2c.88 0 1.4-.72 1.4-1.6v-.33a6.45 6.45 0 0 1 3.83 4.51 6.45 6.45 0 0 1-1.51 5.73v.01Z"></path></svg> <span class="-link--channel-name">Questions</span></a>
|
||
</li>
|
||
<li class="ps-relative" aria-current="false">
|
||
<a id="nav-tags" href="/tags" class="js-gps-track nav-links--link" data-gps-track="top_nav.click({is_current: false, location:2, destination:2})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never">
|
||
<div class="d-flex ai-center">
|
||
<div class="flex--item truncate">
|
||
Tags
|
||
</div>
|
||
</div></a>
|
||
</li>
|
||
<li class="ps-relative" aria-current="false">
|
||
<a id="nav-users" href="/users" class="js-gps-track nav-links--link" data-gps-track="top_nav.click({is_current: false, location:2, destination:3})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never">
|
||
<div class="d-flex ai-center">
|
||
<div class="flex--item truncate">
|
||
Users
|
||
</div>
|
||
</div></a>
|
||
</li>
|
||
<li class="ps-relative" aria-current="false">
|
||
<a id="nav-companies" href="https://stackoverflow.com/jobs/companies?so_medium=stackoverflow&so_source=SiteNav" class="js-gps-track nav-links--link" data-gps-track="top_nav.click({is_current: false, location:2, destination:12})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never">
|
||
<div class="d-flex ai-center">
|
||
<div class="flex--item truncate">
|
||
Companies
|
||
</div>
|
||
</div></a>
|
||
</li>
|
||
<li class="d-flex ml8 mt16 jc-space-between">
|
||
<div class="flex--item tt-uppercase tt-uppercase fs-fine fc-light">
|
||
Collectives
|
||
</div>
|
||
<div class="flex--item fs-fine fc-light">
|
||
<a href="javascript:void(0)" class="s-link s-link__inherit mr8 js-gps-track js-collectives-navcta-toggle" role="button" aria-controls="popover-discover-collectives" data-controller="s-popover" data-action="s-popover#toggle" data-s-popover-placement="top" data-s-popover-toggle-class="is-selected" data-gps-track="top_nav.click({is_current:false, location:2, destination:17})" aria-expanded="false"><svg aria-hidden="true" class="svg-icon iconInfoSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="M7 1a6 6 0 1 1 0 12A6 6 0 0 1 7 1Zm1 10V6H6v5h2Zm0-6V3H6v2h2Z"></path></svg></a>
|
||
</div>
|
||
</li>
|
||
<li class="ps-relative" aria-current="false">
|
||
<a id="nav-collective-discover" href="/collectives" class="pl8 ai-center js-collectives-navcta-toggle js-gps-track nav-links--link -link__with-icon" data-gps-track="top_nav.click({is_current: false, location:2, destination:18})" aria-controls="" data-controller="" data-s-popover-placement="right" aria-current="false" data-s-popover-auto-show="true" data-s-popover-hide-on-outside-click="never"><svg aria-hidden="true" class="mt-auto fc-orange-400 svg-icon iconStarVerified" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M9.86.89a1.14 1.14 0 0 0-1.72 0l-.5.58c-.3.35-.79.48-1.23.33l-.72-.25a1.14 1.14 0 0 0-1.49.85l-.14.76c-.1.45-.45.8-.9.9l-.76.14c-.67.14-1.08.83-.85 1.49l.25.72c.15.44.02.92-.33 1.23l-.58.5a1.14 1.14 0 0 0 0 1.72l.58.5c.35.3.48.79.33 1.23l-.25.72c-.23.66.18 1.35.85 1.49l.76.14c.45.1.8.45.9.9l.14.76c.14.67.83 1.08 1.49.85l.72-.25c.44-.15.92-.02 1.23.33l.5.58c.46.52 1.26.52 1.72 0l.5-.58c.3-.35.79-.48 1.23-.33l.72.25c.66.23 1.35-.18 1.49-.85l.14-.76c.1-.45.45-.8.9-.9l.76-.14c.67-.14 1.08-.83.85-1.49l-.25-.72c-.15-.44-.02-.92.33-1.23l.58-.5c.52-.46.52-1.26 0-1.72l-.58-.5c-.35-.3-.48-.79-.33-1.23l.25-.72a1.14 1.14 0 0 0-.85-1.49l-.76-.14c-.45-.1-.8-.45-.9-.9l-.14-.76a1.14 1.14 0 0 0-1.49-.85l-.72.25c-.44.15-.92.02-1.23-.33l-.5-.58Zm-.49 2.67L10.6 6.6c.05.15.19.24.34.25l3.26.22c.36.03.5.48.23.71l-2.5 2.1a.4.4 0 0 0-.14.4l.8 3.16a.4.4 0 0 1-.6.44L9.2 12.13a.4.4 0 0 0-.42 0l-2.77 1.74a.4.4 0 0 1-.6-.44l.8-3.16a.4.4 0 0 0-.13-.4l-2.5-2.1a.4.4 0 0 1 .22-.7l3.26-.23a.4.4 0 0 0 .34-.25l1.22-3.03a.4.4 0 0 1 .74 0Z"></path></svg> <span class="-link--channel-name">Explore Collectives</span></a>
|
||
</li>
|
||
</ol>
|
||
</li>
|
||
<li>
|
||
<ol class="nav-links">
|
||
<li class="js-freemium-cta ps-relative">
|
||
<div class="fs-fine tt-uppercase ml8 mt16 mb8 fc-light">
|
||
Teams
|
||
</div>
|
||
<div class="bt bl bb bc-black-075 p12 pb6 fc-black-600 blr-sm overflow-hidden">
|
||
<strong class="fc-black-750 mb6">Stack Overflow for Teams</strong> – Start collaborating and sharing organizational knowledge. <img class="wmx100 mx-auto my8 h-auto d-block" width="139" height="114" src="https://cdn.sstatic.net/Img/teams/teams-illo-free-sidebar-promo.svg?v=47faa659a05e" alt="" /> <a href="https://try.stackoverflow.co/why-teams/?utm_source=so-owned&utm_medium=side-bar&utm_campaign=campaign-38&utm_content=cta" class="w100 s-btn s-btn__primary s-btn__xs bg-orange-400 js-gps-track" data-gps-track="teams.create.left-sidenav.click({ Action: 6 })" data-ga="["teams left navigation - anonymous","left nav free cta","stackoverflow.com/teams/create/free",null,null]">Create a free Team</a> <a href="https://stackoverflow.co/teams" class="w100 s-btn s-btn__muted s-btn__xs js-gps-track" data-gps-track="teams.create.left-sidenav.click({ Action: 5 })" data-ga="["teams left navigation - anonymous","left nav free cta","stackoverflow.com/teams",null,null]">Why Teams?</a>
|
||
</div>
|
||
</li>
|
||
<li class="d-flex ai-center jc-space-between ml8 mt24 mb4 js-create-team-cta d-none">
|
||
<div class="flex--item tt-uppercase fs-fine fc-light">
|
||
Teams
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="javascript:void(0)" class="s-link p12 fc-black-500 h:fc-black-800 js-gps-track" role="button" aria-controls="popover-teams-create-cta" data-controller="s-popover" data-action="s-popover#toggle" data-s-popover-placement="bottom-start" data-s-popover-toggle-class="is-selected" data-gps-track="teams.create.left-sidenav.click({ Action: ShowInfo })" data-ga="["teams left navigation - anonymous","left nav show teams info",null,null,null]" aria-expanded="false"><svg aria-hidden="true" class="svg-icon iconInfoSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="M7 1a6 6 0 1 1 0 12A6 6 0 0 1 7 1Zm1 10V6H6v5h2Zm0-6V3H6v2h2Z"></path></svg></a>
|
||
</div>
|
||
</li>
|
||
<li class="ps-relative js-create-team-cta d-none">
|
||
<a href="https://stackoverflowteams.com/teams/create/free?utm_source=so-owned&utm_medium=side-bar&utm_campaign=campaign-38&utm_content=cta" class="pl8 js-gps-track nav-links--link" title="Stack Overflow for Teams is a private, secure spot for your organization's questions and answers." data-gps-track="teams.create.left-sidenav.click({ Action: FreemiumTeamsCreateClick })" data-ga="["teams left navigation - anonymous","left nav team click","stackoverflow.com/teams/create/free",null,null]">
|
||
<div class="d-flex ai-center">
|
||
<div class="flex--item s-avatar va-middle bg-orange-400">
|
||
<div class="s-avatar--letter mtn1">
|
||
<svg aria-hidden="true" class="svg-icon iconBriefcaseSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="M4 3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1h.5c.83 0 1.5.67 1.5 1.5v5c0 .83-.67 1.5-1.5 1.5h-7A1.5 1.5 0 0 1 2 10.5v-5C2 4.67 2.67 4 3.5 4H4V3Zm5 1V3H5v1h4Z"></path></svg>
|
||
</div><svg aria-hidden="true" class="native s-avatar--badge svg-icon iconShieldXSm" width="9" height="10" viewbox="0 0 9 10">
|
||
<path d="M0 1.84 4.5 0 9 1.84v3.17C9 7.53 6.3 10 4.5 10 2.7 10 0 7.53 0 5.01V1.84Z" fill="var(--white)"></path>
|
||
<path d="M1 2.5 4.5 1 8 2.5v2.51C8 7.34 5.34 9 4.5 9 3.65 9 1 7.34 1 5.01V2.5Zm2.98 3.02L3.2 7h2.6l-.78-1.48a.4.4 0 0 1 .15-.38c.34-.24.73-.7.73-1.14 0-.71-.5-1.23-1.41-1.23-.92 0-1.39.52-1.39 1.23 0 .44.4.9.73 1.14.12.08.18.23.15.38Z" fill="var(--black-500)"></path></svg>
|
||
</div>
|
||
<div class="flex--item pl6">
|
||
Create free Team
|
||
</div>
|
||
</div></a>
|
||
</li>
|
||
</ol>
|
||
</li>
|
||
</ol>
|
||
</nav>
|
||
</div>
|
||
<div class="s-popover mt4 ws3" id="teams-are-moving-popover" role="menu">
|
||
<div class="s-popover--arrow"></div>
|
||
<p>
|
||
Stack Overflow for Teams is moving to its own domain! When the migration is complete, you will access your Teams at <span class="fs-italic">stackoverflowteams.com</span>, and they will no longer appear in the left sidebar on <span class="fs-italic">stackoverflow.com</span>.
|
||
</p>
|
||
<p>
|
||
Check your email for updates.
|
||
</p>
|
||
</div>
|
||
<div class="s-popover ws2" id="popover-discover-collectives" role="menu">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<svg aria-hidden="true" class="fc-orange-500 float-right ml24 svg-spot spotCollective" width="48" height="48" viewbox="0 0 48 48">
|
||
<path d="M25.5 7a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM14 18.25c0-.69.56-1.25 1.25-1.25h22.5c.69 0 1.25.56 1.25 1.25V37.5a1 1 0 0 1-1.6.8l-4.07-3.05a1.25 1.25 0 0 0-.75-.25H15.25c-.69 0-1.25-.56-1.25-1.25v-15.5ZM7 24.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0ZM25.5 48a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5ZM48 24.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" opacity=".2"></path>
|
||
<path d="M21 3.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0ZM24.5 2a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3ZM0 23.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0ZM3.5 22a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3ZM21 44.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0Zm3.5-1.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Zm20-23a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7ZM43 23.5a1.5 1.5 0 1 1 3 0 1.5 1.5 0 0 1-3 0Zm-23.23-3.14a1 1 0 0 1-.13 1.4l-2.08 1.74 2.08 1.73a1 1 0 1 1-1.28 1.54l-2.42-2.02a1.63 1.63 0 0 1 0-2.5l2.42-2.02a1 1 0 0 1 1.4.13Zm7.59 1.41a1 1 0 1 1 1.28-1.54l2.42 2.02c.78.65.78 1.85 0 2.5l-2.42 2.02a1 1 0 1 1-1.28-1.54l2.08-1.73-2.08-1.73ZM24.12 18a1 1 0 0 1 .87 1.12l-1 8a1 1 0 1 1-1.98-.24l1-8a1 1 0 0 1 1.11-.87Zm-11.87-5C11.01 13 10 14 10 15.25v15.5c0 1.24 1 2.25 2.25 2.25h17.33c.06 0 .11.02.15.05l4.07 3.05a2 2 0 0 0 3.2-1.6V15.25c0-1.24-1-2.25-2.25-2.25h-22.5ZM12 15.25c0-.14.11-.25.25-.25h22.5c.14 0 .25.11.25.25V34.5l-4.07-3.05a2.2 2.2 0 0 0-1.35-.45H12.25a.25.25 0 0 1-.25-.25v-15.5Zm7.24-10.68a1 1 0 1 0-.48-1.94A22.04 22.04 0 0 0 2.91 17.7a1 1 0 1 0 1.92.58 20.04 20.04 0 0 1 14.4-13.72Zm11.05-1.66a1 1 0 0 0-.58 1.92c6.45 1.92 11.54 7 13.46 13.46a1 1 0 1 0 1.92-.58 22.05 22.05 0 0 0-14.8-14.8ZM4.57 28.76a1 1 0 0 0-1.94.48 22.03 22.03 0 0 0 16.13 16.13 1 1 0 1 0 .48-1.94A20.03 20.03 0 0 1 4.57 28.76Zm40.8.48a1 1 0 1 0-1.94-.48 20.04 20.04 0 0 1-13.72 14.41 1 1 0 0 0 .58 1.92 22.04 22.04 0 0 0 15.08-15.85Z"></path></svg>
|
||
<h5 class="pt4 fw-bold">
|
||
Collectives™ on Stack Overflow
|
||
</h5>
|
||
<p class="my16 fs-caption fc-medium">
|
||
Find centralized, trusted content and collaborate around the technologies you use most.
|
||
</p><a href="/collectives" class="js-gps-track s-btn s-btn__primary s-btn__xs" data-gps-track="top_nav.click({is_current:false, location:2, destination:18})">Learn more about Collectives</a>
|
||
</div>
|
||
</div>
|
||
<div class="s-popover ws2" id="popover-teams-create-cta" role="menu" aria-hidden="true">
|
||
<div class="s-popover--arrow"></div>
|
||
<div class="ps-relative overflow-hidden">
|
||
<p class="mb2">
|
||
<strong>Teams</strong>
|
||
</p>
|
||
<p class="mb12 fs-caption fc-black-400">
|
||
Q&A for work
|
||
</p>
|
||
<p class="mb12 fs-caption fc-medium">
|
||
Connect and share knowledge within a single location that is structured and easy to search.
|
||
</p><a href="https://stackoverflow.co/teams" class="js-gps-track s-btn s-btn__primary s-btn__xs" data-gps-track="teams.create.left-sidenav.click({ Action: CtaClick })" data-ga="["teams left navigation - anonymous","left nav cta","stackoverflow.com/teams",null,null]">Learn more about Teams</a>
|
||
</div>
|
||
<div class="ps-absolute t8 r8">
|
||
<svg aria-hidden="true" class="fc-orange-500 svg-spot spotPeople" width="48" height="48" viewbox="0 0 48 48">
|
||
<path d="M13.5 28a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM7 30a1 1 0 0 1 1-1h11a1 1 0 0 1 1 1v5h11v-5a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v10a2 2 0 0 1-2 2H33v5a1 1 0 0 1-1 1H20a1 1 0 0 1-1-1v-5H8a1 1 0 0 1-1-1V30Zm25-6.5a4.5 4.5 0 1 0 9 0 4.5 4.5 0 0 0-9 0ZM24.5 34a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z" opacity=".2"></path>
|
||
<path d="M16.4 26.08A6 6 0 1 0 7.53 26C5.64 26.06 4 27.52 4 29.45V40a1 1 0 0 0 1 1h9a1 1 0 1 0 0-2h-4v-7a1 1 0 1 0-2 0v7H6v-9.55c0-.73.67-1.45 1.64-1.45H16a1 1 0 0 0 .4-1.92ZM12 18a4 4 0 1 1 0 8 4 4 0 0 1 0-8Zm16.47 14a6 6 0 1 0-8.94 0A3.6 3.6 0 0 0 16 35.5V46a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V35.5c0-1.94-1.64-3.42-3.53-3.5ZM20 28a4 4 0 1 1 8 0 4 4 0 0 1-8 0Zm-.3 6h8.6c1 0 1.7.75 1.7 1.5V45h-2v-7a1 1 0 1 0-2 0v7h-4v-7a1 1 0 1 0-2 0v7h-2v-9.5c0-.75.7-1.5 1.7-1.5ZM42 22c0 1.54-.58 2.94-1.53 4A3.5 3.5 0 0 1 44 29.45V40a1 1 0 0 1-1 1h-9a1 1 0 1 1 0-2h4v-7a1 1 0 1 1 2 0v7h2v-9.55A1.5 1.5 0 0 0 40.48 28H32a1 1 0 0 1-.4-1.92A6 6 0 1 1 42 22Zm-2 0a4 4 0 1 0-8 0 4 4 0 0 0 8 0Z"></path>
|
||
<g opacity=".35">
|
||
<path d="M17 10a1 1 0 011-1h12a1 1 0 110 2H18a1 1 0 01-1-1Zm1-5a1 1 0 100 2h12a1 1 0 100-2H18ZM14 1a1 1 0 00-1 1v12a1 1 0 001 1h5.09l4.2 4.2a1 1 0 001.46-.04l3.7-4.16H34a1 1 0 001-1V2a1 1 0 00-1-1H14Zm1 12V3h18v10h-5a1 1 0 00-.75.34l-3.3 3.7-3.74-3.75a1 1 0 00-.71-.29H15Z"></path>
|
||
</g></svg>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="content" class="snippet-hidden">
|
||
<div itemprop="mainEntity" itemscope="itemscope" itemtype="https://schema.org/Question">
|
||
<link itemprop="image" href="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png?v=c78bd457575a" />
|
||
<div class="inner-content clearfix">
|
||
<div id="question-header" class="d-flex sm:fd-column">
|
||
<h1 itemprop="name" class="fs-headline1 ow-break-word mb8 flex--item fl1">
|
||
<a href="/questions/231767/what-does-the-yield-keyword-do-in-python" class="question-hyperlink">What does the "yield" keyword do in Python?</a>
|
||
</h1>
|
||
<div class="ml12 aside-cta flex--item print:d-none sm:ml0 sm:mb12 sm:order-first sm:as-end">
|
||
<a href="/questions/ask" class="ws-nowrap s-btn s-btn__primary">Ask Question</a>
|
||
</div>
|
||
</div>
|
||
<div class="d-flex fw-wrap pb8 mb16 bb bc-black-075">
|
||
<div class="flex--item ws-nowrap mr16 mb8" title="2008-10-23 22:21:11Z">
|
||
<span class="fc-light mr2">Asked</span> <time itemprop="dateCreated" datetime="2008-10-23T22:21:11">14 years, 1 month ago</time>
|
||
</div>
|
||
<div class="flex--item ws-nowrap mr16 mb8">
|
||
<span class="fc-light mr2">Modified</span> <a href="?lastactivity" class="s-link s-link__inherit" title="2022-11-23 09:21:24Z">yesterday</a>
|
||
</div>
|
||
<div class="flex--item ws-nowrap mb8" title="Viewed 3,093,010 times">
|
||
<span class="fc-light mr2">Viewed</span> 3.1m times
|
||
</div>
|
||
</div>
|
||
<div id="mainbar" role="main" aria-label="question and answers">
|
||
<div class="question js-question" data-questionid="231767" data-position-on-page="0" data-score="12383" id="question">
|
||
<div class="js-zone-container zone-container-main">
|
||
<div id="dfp-tlb" class="everyonelovesstackoverflow everyoneloves__top-leaderboard everyoneloves__leaderboard" data-dfp-zone="true" style="min-height: auto; height: auto; display: none;" data-google-query-id="CIDvo5rDxvsCFQI6KwodbnsJ2w">
|
||
<div id="google_ads_iframe_/248424177/stackoverflow.com/lb/question-pages_0__container__" style="border: 0pt none; width: 728px; height: 0px;"></div>
|
||
</div>
|
||
<div class="js-report-ad-button-container" style="width: 728px"></div>
|
||
</div>
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="231767">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-g7ig5k58"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-g7ig5k58" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This question shows research effort; it is useful and clear
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="12383">
|
||
12383
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-2kxy3k8i"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-2kxy3k8i" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This question does not show any research effort; it is unclear or not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-231767" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="231767" data-post-type-id="1" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-1afbxyp0"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-1afbxyp0" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this question.
|
||
<div class="s-popover--arrow"></div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/231767/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-iwe6o9im"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-iwe6o9im" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="postcell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<div>
|
||
<aside class="s-notice s-notice__info post-notice js-post-notice mb16" role="status">
|
||
<div class="d-flex fd-column fw-nowrap">
|
||
<div class="d-flex fw-nowrap">
|
||
<div class="flex--item mr8">
|
||
<svg aria-hidden="true" class="svg-icon iconLightbulb" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M15 6.38A6.48 6.48 0 0 0 7.78.04h-.02A6.49 6.49 0 0 0 2.05 5.6a6.31 6.31 0 0 0 2.39 5.75c.49.39.76.93.76 1.5v.24c0 1.07.89 1.9 1.92 1.9h2.75c1.04 0 1.92-.83 1.92-1.9v-.2c0-.6.26-1.15.7-1.48A6.32 6.32 0 0 0 15 6.37ZM4.03 5.85A4.49 4.49 0 0 1 8 2.02a4.48 4.48 0 0 1 5 4.36 4.3 4.3 0 0 1-1.72 3.44c-.98.74-1.5 1.9-1.5 3.08v.1H7.2v-.14c0-1.23-.6-2.34-1.53-3.07a4.32 4.32 0 0 1-1.64-3.94ZM10 18a1 1 0 0 0 0-2H7a1 1 0 1 0 0 2h3Z"></path></svg>
|
||
</div>
|
||
<div class="flex--item wmn0 fl1 lh-lg">
|
||
<div class="flex--item fl1 lh-lg">
|
||
<b>Want to improve this post?</b> Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
<p>
|
||
What is the use of the <code>yield</code> keyword in Python? What does it do?
|
||
</p>
|
||
<p>
|
||
For example, I'm trying to understand this code<sup><strong>1</strong></sup>:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">_get_child_candidates</span>(<span class="hljs-params">self, distance, min_dist, max_dist</span>):
|
||
<span class="hljs-keyword">if</span> self._leftchild <span class="hljs-keyword">and</span> distance - max_dist < self._median:
|
||
<span class="hljs-keyword">yield</span> self._leftchild
|
||
<span class="hljs-keyword">if</span> self._rightchild <span class="hljs-keyword">and</span> distance + max_dist >= self._median:
|
||
<span class="hljs-keyword">yield</span> self._rightchild
|
||
</code></pre>
|
||
<p>
|
||
And this is the caller:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">result, candidates = [], [self]
|
||
<span class="hljs-keyword">while</span> candidates:
|
||
node = candidates.pop()
|
||
distance = node._get_dist(obj)
|
||
<span class="hljs-keyword">if</span> distance <= max_dist <span class="hljs-keyword">and</span> distance >= min_dist:
|
||
result.extend(node._values)
|
||
candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
|
||
<span class="hljs-keyword">return</span> result
|
||
</code></pre>
|
||
<p>
|
||
What happens when the method <code>_get_child_candidates</code> is called? Is a list returned? A single element? Is it called again? When will subsequent calls stop?
|
||
</p>
|
||
<hr />
|
||
<sub>1. This piece of code was written by Jochen Schulz (jrschulz), who made a great Python library for metric spaces. This is the link to the complete source: <a href="https://well-adjusted.de/~jrspieker/mspace/" rel="noreferrer">Module mspace</a>.</sub>
|
||
</div>
|
||
<div class="mt24 mb12">
|
||
<div class="post-taglist d-flex gs4 gsy fd-column">
|
||
<div class="d-flex ps-relative fw-wrap">
|
||
<ul class="ml0 list-ls-none js-post-tag-list-wrapper d-inline">
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python" class="post-tag" title="show questions tagged 'python'" aria-label="show questions tagged 'python'" rel="tag" aria-labelledby="python-container">python</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python-3.x" class="post-tag" title="show questions tagged 'python-3.x'" aria-label="show questions tagged 'python-3.x'" rel="tag" aria-labelledby="python-3.x-container">python-3.x</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/generator" class="post-tag" title="show questions tagged 'generator'" aria-label="show questions tagged 'generator'" rel="tag" aria-labelledby="generator-container">generator</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python-2.x" class="post-tag" title="show questions tagged 'python-2.x'" aria-label="show questions tagged 'python-2.x'" rel="tag" aria-labelledby="python-2.x-container">python-2.x</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/yield" class="post-tag" title="show questions tagged 'yield'" aria-label="show questions tagged 'yield'" rel="tag" aria-labelledby="yield-container">yield</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="mb0">
|
||
<div class="mt16 d-flex gs8 gsy fw-wrap jc-end ai-start pt4 mb16">
|
||
<div class="flex--item mr16 fl1 w96">
|
||
<div class="js-post-menu pt2" data-post-id="231767">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/q/231767" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this question" data-gps-track="post.click({ item: 2, priv: 0, post_type: 1 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this question" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="question" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="1" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-0" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-0">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-0">Share a link to this question</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-0" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/231767/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 1 })" title="">Improve this question</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-231767" class="s-btn s-btn__link js-follow-post js-follow-question js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 1 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-m5ynf38v">Follow</button>
|
||
<div id="--stacks-s-tooltip-m5ynf38v" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this question to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/231767/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 1 })">edited <span title="2022-11-23 09:21:24Z" class="relativetime">yesterday</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/8172439/kai-kazuya-ito">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/XmATK.jpg?s=64&g=1" alt="Kai - Kazuya Ito's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/8172439/kai-kazuya-ito">Kai - Kazuya Ito</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 11,860" dir="ltr">11.9k</span><span title="6 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">6</span></span><span class="v-visible-sr">6 gold badges</span><span title="72 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">72</span></span><span class="v-visible-sr">72 silver badges</span><span title="92 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">92</span></span><span class="v-visible-sr">92 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature owner flex--item">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
asked <span title="2008-10-23 22:21:11Z" class="relativetime">Oct 23, 2008 at 22:21</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/18300/alex-s">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/jcyI4.jpg?s=64&g=1" alt="Alex. S.'s user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/18300/alex-s">Alex. S.</a><span class="d-none" itemprop="name">Alex. S.</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 139,684" dir="ltr">140k</span><span title="19 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">19</span></span><span class="v-visible-sr">19 gold badges</span><span title="53 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">53</span></span><span class="v-visible-sr">53 silver badges</span><span title="61 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">61</span></span><span class="v-visible-sr">61 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-231767" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="231767" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-231767" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid answering questions in comments." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-zone-container zone-container-responsive">
|
||
<div id="dfp-isb" class="everyonelovesstackoverflow everyoneloves__inline-sidebar mx-auto" style="min-height: auto; height: auto; display: none;"></div>
|
||
<div class="js-report-ad-button-container mx-auto" style="width: 300px"></div>
|
||
</div>
|
||
<div id="answers">
|
||
<a name="tab-top" id="tab-top"></a>
|
||
<div id="answers-header">
|
||
<div class="answers-subheader d-flex ai-center mb8">
|
||
<div class="flex--item fl1">
|
||
<h2 class="mb0" data-answercount="51">
|
||
51 Answers <span style="display:none;" itemprop="answerCount">51</span>
|
||
</h2>
|
||
</div>
|
||
<div class="flex--item">
|
||
<div class="d-flex g4 gsx ai-center sm:fd-column sm:ai-start">
|
||
<div class="d-flex fd-column ai-end sm:ai-start">
|
||
<label class="flex--item fs-caption" for="answer-sort-dropdown-select-menu">Sorted by:</label> <a class="js-sort-preference-change s-link flex--item fs-fine d-none" data-value="ScoreDesc" href="/questions/231767/what-does-the-yield-keyword-do-in-python?answertab=scoredesc#tab-top">Reset to default</a>
|
||
</div>
|
||
<div class="flex--item s-select">
|
||
<select id="answer-sort-dropdown-select-menu">
|
||
<option value="scoredesc" selected="selected">
|
||
Highest score (default)
|
||
</option>
|
||
<option value="trending">
|
||
Trending (recent votes count more)
|
||
</option>
|
||
<option value="modifieddesc">
|
||
Date modified (newest first)
|
||
</option>
|
||
<option value="createdasc">
|
||
Date created (oldest first)
|
||
</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="s-pagination site1 themed pager-answers">
|
||
<div class="s-pagination--item is-selected" aria-current=""page"">
|
||
1
|
||
</div><a class="s-pagination--item js-pagination-item" href="/questions/231767/what-does-the-yield-keyword-do-in-python?page=2&tab=scoredesc#tab-top" rel="" title="Go to page 2">2</a> <a class="s-pagination--item js-pagination-item" href="/questions/231767/what-does-the-yield-keyword-do-in-python?page=2&tab=scoredesc#tab-top" rel="next" title="Go to page 2">Next</a>
|
||
</div><a name="231855" id="231855"></a>
|
||
<div id="answer-231855" class="answer js-answer accepted-answer js-accepted-answer" data-answerid="231855" data-parentid="231767" data-score="17405" data-position-on-page="1" data-highest-scored="1" data-question-has-accepted-highest-score="1" itemprop="acceptedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="231855">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-f0nhkptd"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-f0nhkptd" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="17405">
|
||
17405
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-2l22sy7r"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-2l22sy7r" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-231855" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="231855" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-0rreh6ye"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-0rreh6ye" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div>
|
||
<div class="js-bounty-award-container flex--item pb4">
|
||
<div class="d-flex fd-column gs4 ai-center">
|
||
<div class="js-bounty-award flex--item s-badge s-badge__bounty s-badge__sm as-center" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-describedby="--stacks-s-tooltip-au0nrrja">
|
||
+600
|
||
</div>
|
||
<div id="--stacks-s-tooltip-au0nrrja" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer has been awarded bounties worth 600 reputation by alecxe, rassa45 and U12-Forward
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/231855/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-ph8iy60j"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-ph8iy60j" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
To understand what <code>yield</code> does, you must understand what <em>generators</em> are. And before you can understand generators, you must understand <em>iterables</em>.
|
||
</p>
|
||
<h2>
|
||
Iterables
|
||
</h2>
|
||
<p>
|
||
When you create a list, you can read its items one by one. Reading its items one by one is called iteration:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>mylist = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mylist:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">2</span>
|
||
<span class="hljs-number">3</span>
|
||
</code></pre>
|
||
<p>
|
||
<code>mylist</code> is an <em>iterable</em>. When you use a list comprehension, you create a list, and so an iterable:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>mylist = [x*x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>)]
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mylist:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
</code></pre>
|
||
<p>
|
||
Everything you can use "<code>for... in...</code>" on is an iterable; <code>lists</code>, <code>strings</code>, files...
|
||
</p>
|
||
<p>
|
||
These iterables are handy because you can read them as much as you wish, but you store all the values in memory and this is not always what you want when you have a lot of values.
|
||
</p>
|
||
<h2>
|
||
Generators
|
||
</h2>
|
||
<p>
|
||
Generators are iterators, a kind of iterable <strong>you can only iterate over once</strong>. Generators do not store all the values in memory, <strong>they generate the values on the fly</strong>:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>mygenerator = (x*x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>))
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mygenerator:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
</code></pre>
|
||
<p>
|
||
It is just the same except you used <code>()</code> instead of <code>[]</code>. BUT, you <strong>cannot</strong> perform <code>for i in mygenerator</code> a second time since generators can only be used once: they calculate 0, then forget about it and calculate 1, and end calculating 4, one by one.
|
||
</p>
|
||
<h2>
|
||
Yield
|
||
</h2>
|
||
<p>
|
||
<code>yield</code> is a keyword that is used like <code>return</code>, except the function will return a generator.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">def</span> <span class="hljs-title function_">create_generator</span>():
|
||
<span class="hljs-meta">... </span> mylist = <span class="hljs-built_in">range</span>(<span class="hljs-number">3</span>)
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mylist:
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> i*i
|
||
...
|
||
<span class="hljs-meta">>>> </span>mygenerator = create_generator() <span class="hljs-comment"># create a generator</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(mygenerator) <span class="hljs-comment"># mygenerator is an object!</span>
|
||
<generator <span class="hljs-built_in">object</span> create_generator at <span class="hljs-number">0xb7555c34</span>>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> mygenerator:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
</code></pre>
|
||
<p>
|
||
Here it's a useless example, but it's handy when you know your function will return a huge set of values that you will only need to read once.
|
||
</p>
|
||
<p>
|
||
To master <code>yield</code>, you must understand that <strong>when you call the function, the code you have written in the function body does not run.</strong> The function only returns the generator object, this is a bit tricky.
|
||
</p>
|
||
<p>
|
||
Then, your code will continue from where it left off each time <code>for</code> uses the generator.
|
||
</p>
|
||
<p>
|
||
Now the hard part:
|
||
</p>
|
||
<p>
|
||
The first time the <code>for</code> calls the generator object created from your function, it will run the code in your function from the beginning until it hits <code>yield</code>, then it'll return the first value of the loop. Then, each subsequent call will run another iteration of the loop you have written in the function and return the next value. This will continue until the generator is considered empty, which happens when the function runs without hitting <code>yield</code>. That can be because the loop has come to an end, or because you no longer satisfy an <code>"if/else"</code>.
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
Your code explained
|
||
</h2>
|
||
<p>
|
||
<em>Generator:</em>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-comment"># Here you create the method of the node object that will return the generator</span>
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_get_child_candidates</span>(<span class="hljs-params">self, distance, min_dist, max_dist</span>):
|
||
|
||
<span class="hljs-comment"># Here is the code that will be called each time you use the generator object:</span>
|
||
|
||
<span class="hljs-comment"># If there is still a child of the node object on its left</span>
|
||
<span class="hljs-comment"># AND if the distance is ok, return the next child</span>
|
||
<span class="hljs-keyword">if</span> self._leftchild <span class="hljs-keyword">and</span> distance - max_dist < self._median:
|
||
<span class="hljs-keyword">yield</span> self._leftchild
|
||
|
||
<span class="hljs-comment"># If there is still a child of the node object on its right</span>
|
||
<span class="hljs-comment"># AND if the distance is ok, return the next child</span>
|
||
<span class="hljs-keyword">if</span> self._rightchild <span class="hljs-keyword">and</span> distance + max_dist >= self._median:
|
||
<span class="hljs-keyword">yield</span> self._rightchild
|
||
|
||
<span class="hljs-comment"># If the function arrives here, the generator will be considered empty</span>
|
||
<span class="hljs-comment"># there are no more than two values: the left and the right children</span>
|
||
</code></pre>
|
||
<p>
|
||
<em>Caller:</em>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-comment"># Create an empty list and a list with the current object reference</span>
|
||
result, candidates = <span class="hljs-built_in">list</span>(), [self]
|
||
|
||
<span class="hljs-comment"># Loop on candidates (they contain only one element at the beginning)</span>
|
||
<span class="hljs-keyword">while</span> candidates:
|
||
|
||
<span class="hljs-comment"># Get the last candidate and remove it from the list</span>
|
||
node = candidates.pop()
|
||
|
||
<span class="hljs-comment"># Get the distance between obj and the candidate</span>
|
||
distance = node._get_dist(obj)
|
||
|
||
<span class="hljs-comment"># If the distance is ok, then you can fill in the result</span>
|
||
<span class="hljs-keyword">if</span> distance <= max_dist <span class="hljs-keyword">and</span> distance >= min_dist:
|
||
result.extend(node._values)
|
||
|
||
<span class="hljs-comment"># Add the children of the candidate to the candidate's list</span>
|
||
<span class="hljs-comment"># so the loop will keep running until it has looked</span>
|
||
<span class="hljs-comment"># at all the children of the children of the children, etc. of the candidate</span>
|
||
candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
|
||
|
||
<span class="hljs-keyword">return</span> result
|
||
</code></pre>
|
||
<p>
|
||
This code contains several smart parts:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<p>
|
||
The loop iterates on a list, but the list expands while the loop is being iterated. It's a concise way to go through all these nested data even if it's a bit dangerous since you can end up with an infinite loop. In this case, <code>candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))</code> exhausts all the values of the generator, but <code>while</code> keeps creating new generator objects which will produce different values from the previous ones since it's not applied on the same node.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
The <code>extend()</code> method is a list object method that expects an iterable and adds its values to the list.
|
||
</p>
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
Usually, we pass a list to it:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>a = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
|
||
<span class="hljs-meta">>>> </span>b = [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
<span class="hljs-meta">>>> </span>a.extend(b)
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(a)
|
||
[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
</code></pre>
|
||
<p>
|
||
But in your code, it gets a generator, which is good because:
|
||
</p>
|
||
<ol>
|
||
<li>You don't need to read the values twice.
|
||
</li>
|
||
<li>You may have a lot of children and you don't want them all stored in memory.
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
And it works because Python does not care if the argument of a method is a list or not. Python expects iterables so it will work with strings, lists, tuples, and generators! This is called duck typing and is one of the reasons why Python is so cool. But this is another story, for another question...
|
||
</p>
|
||
<p>
|
||
You can stop here, or read a little bit to see an advanced use of a generator:
|
||
</p>
|
||
<h2>
|
||
Controlling a generator exhaustion
|
||
</h2>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">class</span> <span class="hljs-title class_">Bank</span>(): <span class="hljs-comment"># Let's create a bank, building ATMs</span>
|
||
<span class="hljs-meta">... </span> crisis = <span class="hljs-literal">False</span>
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">create_atm</span>(<span class="hljs-params">self</span>):
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> self.crisis:
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> <span class="hljs-string">"$100"</span>
|
||
<span class="hljs-meta">>>> </span>hsbc = Bank() <span class="hljs-comment"># When everything's ok the ATM gives you as much as you want</span>
|
||
<span class="hljs-meta">>>> </span>corner_street_atm = hsbc.create_atm()
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(corner_street_atm.<span class="hljs-built_in">next</span>())
|
||
$<span class="hljs-number">100</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(corner_street_atm.<span class="hljs-built_in">next</span>())
|
||
$<span class="hljs-number">100</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>([corner_street_atm.<span class="hljs-built_in">next</span>() <span class="hljs-keyword">for</span> cash <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">5</span>)])
|
||
[<span class="hljs-string">'$100'</span>, <span class="hljs-string">'$100'</span>, <span class="hljs-string">'$100'</span>, <span class="hljs-string">'$100'</span>, <span class="hljs-string">'$100'</span>]
|
||
<span class="hljs-meta">>>> </span>hsbc.crisis = <span class="hljs-literal">True</span> <span class="hljs-comment"># Crisis is coming, no more money!</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(corner_street_atm.<span class="hljs-built_in">next</span>())
|
||
<<span class="hljs-built_in">type</span> <span class="hljs-string">'exceptions.StopIteration'</span>>
|
||
<span class="hljs-meta">>>> </span>wall_street_atm = hsbc.create_atm() <span class="hljs-comment"># It's even true for new ATMs</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(wall_street_atm.<span class="hljs-built_in">next</span>())
|
||
<<span class="hljs-built_in">type</span> <span class="hljs-string">'exceptions.StopIteration'</span>>
|
||
<span class="hljs-meta">>>> </span>hsbc.crisis = <span class="hljs-literal">False</span> <span class="hljs-comment"># The trouble is, even post-crisis the ATM remains empty</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(corner_street_atm.<span class="hljs-built_in">next</span>())
|
||
<<span class="hljs-built_in">type</span> <span class="hljs-string">'exceptions.StopIteration'</span>>
|
||
<span class="hljs-meta">>>> </span>brand_new_atm = hsbc.create_atm() <span class="hljs-comment"># Build a new one to get back in business</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> cash <span class="hljs-keyword">in</span> brand_new_atm:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span> cash
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
$<span class="hljs-number">100</span>
|
||
...
|
||
</code></pre>
|
||
<p>
|
||
<strong>Note:</strong> For Python 3, use<code>print(corner_street_atm.__next__())</code> or <code>print(next(corner_street_atm))</code>
|
||
</p>
|
||
<p>
|
||
It can be useful for various things like controlling access to a resource.
|
||
</p>
|
||
<h2>
|
||
Itertools, your best friend
|
||
</h2>
|
||
<p>
|
||
The itertools module contains special functions to manipulate iterables. Ever wish to duplicate a generator? Chain two generators? Group values in a nested list with a one-liner? <code>Map / Zip</code> without creating another list?
|
||
</p>
|
||
<p>
|
||
Then just <code>import itertools</code>.
|
||
</p>
|
||
<p>
|
||
An example? Let's see the possible orders of arrival for a four-horse race:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>horses = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
<span class="hljs-meta">>>> </span>races = itertools.permutations(horses)
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(races)
|
||
<itertools.permutations <span class="hljs-built_in">object</span> at <span class="hljs-number">0xb754f1dc</span>>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">print</span>(<span class="hljs-built_in">list</span>(itertools.permutations(horses)))
|
||
[(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>),
|
||
(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>)]
|
||
</code></pre>
|
||
<h2>
|
||
Understanding the inner mechanisms of iteration
|
||
</h2>
|
||
<p>
|
||
Iteration is a process implying iterables (implementing the <code>__iter__()</code> method) and iterators (implementing the <code>__next__()</code> method). Iterables are any objects you can get an iterator from. Iterators are objects that let you iterate on iterables.
|
||
</p>
|
||
<p>
|
||
There is more about it in this article about <a href="https://web.archive.org/web/20201109034340/http://effbot.org/zone/python-for-statement.htm" rel="noreferrer">how <code>for</code> loops work</a>.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="231855">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/231855" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-1" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-1">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-1">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-1" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/231855/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-231855" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-e78m0jys">Follow</button>
|
||
<div id="--stacks-s-tooltip-e78m0jys" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/231855/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2022-10-01 18:08:35Z" class="relativetime">Oct 1 at 18:08</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/14200577/saket-thakur">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://lh3.googleusercontent.com/a-/AOh14GiqTaUES1gAUWFli86iB5KKNAosqQZcUqB07p6F-A=k-s64" alt="Saket Thakur's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/14200577/saket-thakur">Saket Thakur</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">15</span><span title="3 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-23 22:48:44Z" class="relativetime">Oct 23, 2008 at 22:48</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/9951/e-satis">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/?s=64&d=identicon&r=PG&f=1" alt="e-satis's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/9951/e-satis">e-satis</a><span class="d-none" itemprop="name">e-satis</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 564,577" dir="ltr">565k</span><span title="110 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">110</span></span><span class="v-visible-sr">110 gold badges</span><span title="294 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">294</span></span><span class="v-visible-sr">294 silver badges</span><span title="328 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">328</span></span><span class="v-visible-sr">328 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">9</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-231855" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="231855" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="4" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-75308701" class="comment js-comment" data-comment-id="75308701" data-comment-owner-id="3830997" data-comment-score="674">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">674</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy"><code>yield</code> is not as magical this answer suggests. When you call a function that contains a <code>yield</code> statement anywhere, you get a generator object, but no code runs. Then each time you extract an object from the generator, Python executes code in the function until it comes to a <code>yield</code> statement, then pauses and delivers the object. When you extract another object, Python resumes just after the <code>yield</code> and continues until it reaches another <code>yield</code> (often the same one, but one iteration later). This continues until the function runs off the end, at which point the generator is deemed exhausted.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/3830997/matthias-fripp" title="16,946 reputation" class="comment-user">Matthias Fripp</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment75308701_231855" aria-label="Link to comment"><span title="2017-05-23 21:41:53Z, License: CC BY-SA 3.0" class="relativetime-clean">May 23, 2017 at 21:41</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-84633217" class="comment js-comment" data-comment-id="84633217" data-comment-owner-id="557022" data-comment-score="74">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">74</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">"These iterables are handy... but you store all the values in memory and this is not always what you want", is either wrong or confusing. An iterable returns an iterator upon calling the iter() on the iterable, and an iterator doesn't always have to store its values in memory, depending on the implementation of the <b>iter</b> method, it can also generate values in the sequence on demand.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/557022/picmate-%e6%b6%85" title="3,733 reputation" class="comment-user">picmate 涅</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment84633217_231855" aria-label="Link to comment"><span title="2018-02-15 19:21:11Z, License: CC BY-SA 3.0" class="relativetime-clean">Feb 15, 2018 at 19:21</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-109059326" class="comment js-comment" data-comment-id="109059326" data-comment-owner-id="903011" data-comment-score="25">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="hot">25</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">It would be nice to add to this <b>great</b> answer why <i>It is just the same except you used <code>()</code> instead of <code>[]</code></i>, specifically what <code>()</code> is (there may be confusion with a tuple).</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/903011/woj" title="24,663 reputation" class="comment-user">WoJ</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment109059326_231855" aria-label="Link to comment"><span title="2020-05-07 10:12:21Z, License: CC BY-SA 4.0" class="relativetime-clean">May 7, 2020 at 10:12</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-110055463" class="comment js-comment" data-comment-id="110055463" data-comment-owner-id="13596037" data-comment-score="40">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">40</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">@MatthiasFripp "This continues until the function runs off the end" -- or it encounters a <code>return</code> statement. (<code>return</code> is permitted in a function containing <code>yield</code>, provided that it does not specify a return value.)</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/13596037/alani" title="12,263 reputation" class="comment-user">alani</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment110055463_231855" aria-label="Link to comment"><span title="2020-06-06 06:03:41Z, License: CC BY-SA 4.0" class="relativetime-clean">Jun 6, 2020 at 6:03</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-115124375" class="comment js-comment" data-comment-id="115124375" data-comment-owner-id="14527222" data-comment-score="7">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="warm">7</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">The yield statement suspends function’s execution and sends a value back to the caller, but retains enough state to enable function to resume where it is left off. When resumed, the function continues execution immediately after the last yield run. This allows its code to produce a series of values over time, rather than computing them at once and sending them back like a list.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/14527222/jacob-ward" title="201 reputation" class="comment-user">Jacob Ward</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment115124375_231855" aria-label="Link to comment"><span title="2020-12-03 01:23:36Z, License: CC BY-SA 4.0" class="relativetime-clean">Dec 3, 2020 at 1:23</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-231855" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link dno" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button"></a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link" title="Expand to show all comments on this post" href="#" onclick="" role="button">Show <b>4</b> more comments</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-zone-container zone-container-main">
|
||
<div id="dfp-mlb" class="everyonelovesstackoverflow everyoneloves__mid-leaderboard everyoneloves__leaderboard" style="min-height: auto; height: auto; display: none;" data-google-query-id="CLXto5rDxvsCFREkcgodyFcAJw">
|
||
<div id="google_ads_iframe_/248424177/stackoverflow.com/mlb/question-pages_0__container__" style="border: 0pt none; width: 728px; height: 0px;"></div>
|
||
</div>
|
||
<div class="js-report-ad-button-container" style="width: 728px"></div>
|
||
</div><a name="237028" id="237028"></a>
|
||
<div id="answer-237028" class="answer js-answer" data-answerid="237028" data-parentid="231767" data-score="2426" data-position-on-page="2" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="237028">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zwcdai28"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zwcdai28" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="2426">
|
||
2426
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-po867ckv"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-po867ckv" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-237028" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="237028" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-vcszq3ih"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-vcszq3ih" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/237028/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-qdf8rj2w"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-qdf8rj2w" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<h2>
|
||
Shortcut to understanding <code>yield</code>
|
||
</h2>
|
||
<p>
|
||
When you see a function with <code>yield</code> statements, apply this easy trick to understand what will happen:
|
||
</p>
|
||
<ol>
|
||
<li>Insert a line <code>result = []</code> at the start of the function.
|
||
</li>
|
||
<li>Replace each <code>yield expr</code> with <code>result.append(expr)</code>.
|
||
</li>
|
||
<li>Insert a line <code>return result</code> at the bottom of the function.
|
||
</li>
|
||
<li>Yay - no more <code>yield</code> statements! Read and figure out the code.
|
||
</li>
|
||
<li>Compare function to the original definition.
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
This trick may give you an idea of the logic behind the function, but what actually happens with <code>yield</code> is significantly different than what happens in the list-based approach. In many cases, the yield approach will be a lot more memory efficient and faster too. In other cases, this trick will get you stuck in an infinite loop, even though the original function works just fine. Read on to learn more...
|
||
</p>
|
||
<h2>
|
||
Don't confuse your Iterables, Iterators, and Generators
|
||
</h2>
|
||
<p>
|
||
First, the <strong>iterator protocol</strong> - when you write
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> mylist:
|
||
...loop body...
|
||
</code></pre>
|
||
<p>
|
||
Python performs the following two steps:
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
<p>
|
||
Gets an iterator for <code>mylist</code>:
|
||
</p>
|
||
<p>
|
||
Call <code>iter(mylist)</code> -> this returns an object with a <code>next()</code> method (or <code>__next__()</code> in Python 3).
|
||
</p>
|
||
<p>
|
||
[This is the step most people forget to tell you about]
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
Uses the iterator to loop over items:
|
||
</p>
|
||
<p>
|
||
Keep calling the <code>next()</code> method on the iterator returned from step 1. The return value from <code>next()</code> is assigned to <code>x</code> and the loop body is executed. If an exception <code>StopIteration</code> is raised from within <code>next()</code>, it means there are no more values in the iterator and the loop is exited.
|
||
</p>
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
The truth is Python performs the above two steps anytime it wants to <em>loop over</em> the contents of an object - so it could be a for loop, but it could also be code like <code>otherlist.extend(mylist)</code> (where <code>otherlist</code> is a Python list).
|
||
</p>
|
||
<p>
|
||
Here <code>mylist</code> is an <em>iterable</em> because it implements the iterator protocol. In a user-defined class, you can implement the <code>__iter__()</code> method to make instances of your class iterable. This method should return an <em>iterator</em>. An iterator is an object with a <code>next()</code> method. It is possible to implement both <code>__iter__()</code> and <code>next()</code> on the same class, and have <code>__iter__()</code> return <code>self</code>. This will work for simple cases, but not when you want two iterators looping over the same object at the same time.
|
||
</p>
|
||
<p>
|
||
So that's the iterator protocol, many objects implement this protocol:
|
||
</p>
|
||
<ol>
|
||
<li>Built-in lists, dictionaries, tuples, sets, and files.
|
||
</li>
|
||
<li>User-defined classes that implement <code>__iter__()</code>.
|
||
</li>
|
||
<li>Generators.
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
Note that a <code>for</code> loop doesn't know what kind of object it's dealing with - it just follows the iterator protocol, and is happy to get item after item as it calls <code>next()</code>. Built-in lists return their items one by one, dictionaries return the <em>keys</em> one by one, files return the <em>lines</em> one by one, etc. And generators return... well that's where <code>yield</code> comes in:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f123</span>():
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">2</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">3</span>
|
||
|
||
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> f123():
|
||
<span class="hljs-built_in">print</span> item
|
||
</code></pre>
|
||
<p>
|
||
Instead of <code>yield</code> statements, if you had three <code>return</code> statements in <code>f123()</code> only the first would get executed, and the function would exit. But <code>f123()</code> is no ordinary function. When <code>f123()</code> is called, it <em>does not</em> return any of the values in the yield statements! It returns a generator object. Also, the function does not really exit - it goes into a suspended state. When the <code>for</code> loop tries to loop over the generator object, the function resumes from its suspended state at the very next line after the <code>yield</code> it previously returned from, executes the next line of code, in this case, a <code>yield</code> statement, and returns that as the next item. This happens until the function exits, at which point the generator raises <code>StopIteration</code>, and the loop exits.
|
||
</p>
|
||
<p>
|
||
So the generator object is sort of like an adapter - at one end it exhibits the iterator protocol, by exposing <code>__iter__()</code> and <code>next()</code> methods to keep the <code>for</code> loop happy. At the other end, however, it runs the function just enough to get the next value out of it, and puts it back in suspended mode.
|
||
</p>
|
||
<h2>
|
||
Why Use Generators?
|
||
</h2>
|
||
<p>
|
||
Usually, you can write code that doesn't use generators but implements the same logic. One option is to use the temporary list 'trick' I mentioned before. That will not work in all cases, for e.g. if you have infinite loops, or it may make inefficient use of memory when you have a really long list. The other approach is to implement a new iterable class SomethingIter that keeps the state in instance members and performs the next logical step in its <code>next()</code> (or <code>__next__()</code> in Python 3) method. Depending on the logic, the code inside the <code>next()</code> method may end up looking very complex and prone to bugs. Here generators provide a clean and easy solution.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="237028">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/237028" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-2" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-2">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-2">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-2" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/237028/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-237028" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-p7a6ro9f">Follow</button>
|
||
<div id="--stacks-s-tooltip-p7a6ro9f" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/237028/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2022-10-01 21:06:05Z" class="relativetime">Oct 1 at 21:06</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/14200577/saket-thakur">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://lh3.googleusercontent.com/a-/AOh14GiqTaUES1gAUWFli86iB5KKNAosqQZcUqB07p6F-A=k-s64" alt="Saket Thakur's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/14200577/saket-thakur">Saket Thakur</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">15</span><span title="3 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-25 21:22:30Z" class="relativetime">Oct 25, 2008 at 21:22</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/28409/user28409">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/?s=64&d=identicon&r=PG" alt="user28409's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/28409/user28409">user28409</a><span class="d-none" itemprop="name">user28409</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 37,344" dir="ltr">37.3k</span><span title="2 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">2</span></span><span class="v-visible-sr">2 gold badges</span><span title="17 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">17</span></span><span class="v-visible-sr">17 silver badges</span><span title="5 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">5</span></span><span class="v-visible-sr">5 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">3</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-237028" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="237028" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-76206780" class="comment js-comment" data-comment-id="76206780" data-comment-owner-id="2665591" data-comment-score="39">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">39</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy"><i>"When you see a function with yield statements, apply this easy trick to understand what will happen"</i> Doesn't this completely ignore the fact that you can <code>send</code> into a generator, which is a huge part of the point of generators?</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/2665591/danielsank" title="3,219 reputation" class="comment-user">DanielSank</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment76206780_237028" aria-label="Link to comment"><span title="2017-06-17 22:41:34Z, License: CC BY-SA 3.0" class="relativetime-clean">Jun 17, 2017 at 22:41</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-79407236" class="comment js-comment" data-comment-id="79407236" data-comment-owner-id="406776" data-comment-score="16">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="hot">16</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">"it could be a for loop, but it could also be code like <code>otherlist.extend(mylist)</code>" -> This is incorrect. <code>extend()</code> modifies the list in-place and does not return an iterable. Trying to loop over <code>otherlist.extend(mylist)</code> will fail with a <code>TypeError</code> because <code>extend()</code> implicitly returns <code>None</code>, and you can't loop over <code>None</code>.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/406776/pedro" title="365 reputation" class="comment-user">Pedro</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment79407236_237028" aria-label="Link to comment"><span title="2017-09-14 14:48:17Z, License: CC BY-SA 3.0" class="relativetime-clean">Sep 14, 2017 at 14:48</span></a></span> <span title="this comment was edited 2 times"><svg aria-hidden="true" class="va-text-bottom o50 svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-82933650" class="comment js-comment" data-comment-id="82933650" data-comment-owner-id="2099607" data-comment-score="13">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="warm">13</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">@pedro You have misunderstood that sentence. It means that python performs the two mentioned steps on <code>mylist</code> (not on <code>otherlist</code>) when executing <code>otherlist.extend(mylist)</code>.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/2099607/today" title="31,572 reputation" class="comment-user">today</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment82933650_237028" aria-label="Link to comment"><span title="2017-12-26 18:53:57Z, License: CC BY-SA 3.0" class="relativetime-clean">Dec 26, 2017 at 18:53</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-237028" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="231801" id="231801"></a>
|
||
<div id="answer-231801" class="answer js-answer" data-answerid="231801" data-parentid="231767" data-score="720" data-position-on-page="3" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="231801">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zh6nw09v"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zh6nw09v" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="720">
|
||
720
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-2g1zsbex"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-2g1zsbex" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-231801" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="231801" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-vxrpv1rv"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-vxrpv1rv" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/231801/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-qryaanmd"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-qryaanmd" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Think of it this way:
|
||
</p>
|
||
<p>
|
||
An iterator is just a fancy sounding term for an object that has a <code>next()</code> method. So a yield-ed function ends up being something like this:
|
||
</p>
|
||
<p>
|
||
Original version:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">some_function</span>():
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> xrange(<span class="hljs-number">4</span>):
|
||
<span class="hljs-keyword">yield</span> i
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> some_function():
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
This is basically what the Python interpreter does with the above code:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">it</span>:
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
|
||
<span class="hljs-comment"># Start at -1 so that we get 0 when we add 1 below.</span>
|
||
self.count = -<span class="hljs-number">1</span>
|
||
|
||
<span class="hljs-comment"># The __iter__ method will be called once by the 'for' loop.</span>
|
||
<span class="hljs-comment"># The rest of the magic happens on the object returned by this method.</span>
|
||
<span class="hljs-comment"># In this case it is the object itself.</span>
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__iter__</span>(<span class="hljs-params">self</span>):
|
||
<span class="hljs-keyword">return</span> self
|
||
|
||
<span class="hljs-comment"># The next method will be called repeatedly by the 'for' loop</span>
|
||
<span class="hljs-comment"># until it raises StopIteration.</span>
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">next</span>(<span class="hljs-params">self</span>):
|
||
self.count += <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">if</span> self.count < <span class="hljs-number">4</span>:
|
||
<span class="hljs-keyword">return</span> self.count
|
||
<span class="hljs-keyword">else</span>:
|
||
<span class="hljs-comment"># A StopIteration exception is raised</span>
|
||
<span class="hljs-comment"># to signal that the iterator is done.</span>
|
||
<span class="hljs-comment"># This is caught implicitly by the 'for' loop.</span>
|
||
<span class="hljs-keyword">raise</span> StopIteration
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">some_func</span>():
|
||
<span class="hljs-keyword">return</span> it()
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> some_func():
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
For more insight as to what's happening behind the scenes, the <code>for</code> loop can be rewritten to this:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">iterator = some_func()
|
||
<span class="hljs-keyword">try</span>:
|
||
<span class="hljs-keyword">while</span> <span class="hljs-number">1</span>:
|
||
<span class="hljs-built_in">print</span> iterator.<span class="hljs-built_in">next</span>()
|
||
<span class="hljs-keyword">except</span> StopIteration:
|
||
<span class="hljs-keyword">pass</span>
|
||
</code></pre>
|
||
<p>
|
||
Does that make more sense or just confuse you more? :)
|
||
</p>
|
||
<p>
|
||
I should note that this <em>is</em> an oversimplification for illustrative purposes. :)
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="231801">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/231801" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-3" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-3">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-3">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-3" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/231801/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-231801" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-tgygjhlf">Follow</button>
|
||
<div id="--stacks-s-tooltip-tgygjhlf" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/231801/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2019-05-07 13:28:35Z" class="relativetime">May 7, 2019 at 13:28</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/7851470/georgy">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/d10f0dc1bc1f340708d6f6b4c8ec3866?s=64&d=identicon&r=PG&f=1" alt="Georgy's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/7851470/georgy">Georgy</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 11,134" dir="ltr">11.1k</span><span title="7 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">7</span></span><span class="v-visible-sr">7 gold badges</span><span title="62 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">62</span></span><span class="v-visible-sr">62 silver badges</span><span title="70 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">70</span></span><span class="v-visible-sr">70 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-23 22:28:41Z" class="relativetime">Oct 23, 2008 at 22:28</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2147/jason-baker">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/b8e26b9942e7193a4fe32c407aacfef5?s=64&d=identicon&r=PG" alt="Jason Baker's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/2147/jason-baker">Jason Baker</a><span class="d-none" itemprop="name">Jason Baker</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 186,691" dir="ltr">187k</span><span title="133 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">133</span></span><span class="v-visible-sr">133 gold badges</span><span title="370 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">370</span></span><span class="v-visible-sr">370 silver badges</span><span title="510 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">510</span></span><span class="v-visible-sr">510 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">4</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-231801" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="231801" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-100409" class="comment js-comment" data-comment-id="100409" data-comment-owner-id="4279" data-comment-score="1">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="cool">1</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy"><code>__getitem__</code> could be defined instead of <code>__iter__</code>. For example: <code>class it: pass; it.__getitem__ = lambda self, i: i*10 if i < 10 else [][0]; for i in it(): print(i)</code>, It will print: 0, 10, 20, ..., 90</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/4279/jfs" title="385,709 reputation" class="comment-user">jfs</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment100409_231801" aria-label="Link to comment"><span title="2008-10-25 02:03:38Z, License: CC BY-SA 2.5" class="relativetime-clean">Oct 25, 2008 at 2:03</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-74681581" class="comment js-comment" data-comment-id="74681581" data-comment-owner-id="4138739" data-comment-score="33">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">33</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">I tried this example in Python 3.6 and if I create <code>iterator = some_function()</code>, the variable <code>iterator</code> does not have a function called <code>next()</code> anymore, but only a <code>__next__()</code> function. Thought I'd mention it.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/4138739/peter" title="1,070 reputation" class="comment-user">Peter</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment74681581_231801" aria-label="Link to comment"><span title="2017-05-06 14:37:55Z, License: CC BY-SA 3.0" class="relativetime-clean">May 6, 2017 at 14:37</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-109209205" class="comment js-comment" data-comment-id="109209205" data-comment-owner-id="11707607" data-comment-score="0">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide"></div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">Where does the <code>for</code> loop implementation you wrote call the <code>__iter__</code> method of <code>iterator</code>, the instantiated instance of <code>it</code>?</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/11707607/systematicdisintegration" title="121 reputation" class="comment-user">SystematicDisintegration</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment109209205_231801" aria-label="Link to comment"><span title="2020-05-11 22:50:42Z, License: CC BY-SA 4.0" class="relativetime-clean">May 11, 2020 at 22:50</span></a></span> <span title="this comment was edited 1 time"><svg aria-hidden="true" class="va-text-bottom o50 svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-113829987" class="comment js-comment" data-comment-id="113829987" data-comment-owner-id="10403090" data-comment-score="0">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide"></div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">Unfortunately this answer is not true at all. This is not what python interpreter does with generators. It is not creating a class starting from the generator function and implement <code>__iter__</code> and <code>__next__</code>. What it is acutally doing under the hood is explained in this post <a href="https://stackoverflow.com/questions/45723893/how-does-a-generator-function-work-internally#comment78413677_45727729" title="how does a generator function work internally%23comment78413677_45727729">stackoverflow.com/questions/45723893/…</a>. To cite @Raymond Hettinger <i>"generators are not implemented internally as shown in your pure python class. Instead, they share most of the same logic as regular functions"</i></span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/10403090/gioxc88" title="349 reputation" class="comment-user">gioxc88</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment113829987_231801" aria-label="Link to comment"><span title="2020-10-15 13:52:39Z, License: CC BY-SA 4.0" class="relativetime-clean">Oct 15, 2020 at 13:52</span></a></span> <span title="this comment was edited 3 times"><svg aria-hidden="true" class="va-text-bottom o50 svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-231801" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-zone-container zone-container-main">
|
||
<div id="dfp-smlb" class="everyonelovesstackoverflow everyoneloves__mid-second-leaderboard everyoneloves__leaderboard" style="min-height: auto; height: auto; display: none;" data-google-query-id="CJf8o5rDxvsCFdQRcgodPZgI4A">
|
||
<div id="google_ads_iframe_/248424177/stackoverflow.com/smlb/question-pages_0__container__" style="border: 0pt none; width: 728px; height: 0px;"></div>
|
||
</div>
|
||
<div class="js-report-ad-button-container" style="width: 728px"></div>
|
||
</div><a name="6400990" id="6400990"></a>
|
||
<div id="answer-6400990" class="answer js-answer" data-answerid="6400990" data-parentid="231767" data-score="610" data-position-on-page="4" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="6400990">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-9o9hi0ij"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-9o9hi0ij" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="610">
|
||
610
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zgt6tzkt"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zgt6tzkt" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-6400990" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="6400990" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-k276i2h8"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-k276i2h8" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/6400990/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-z6zvpmot"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-z6zvpmot" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
The <code>yield</code> keyword is reduced to two simple facts:
|
||
</p>
|
||
<ol>
|
||
<li>If the compiler detects the <code>yield</code> keyword <em>anywhere</em> inside a function, that function no longer returns via the <code>return</code> statement. <em><strong>Instead</strong></em>, it <strong>immediately</strong> returns a <strong>lazy "pending list" object</strong> called a generator
|
||
</li>
|
||
<li>A generator is iterable. What is an <em>iterable</em>? It's anything like a <code>list</code> or <code>set</code> or <code>range</code> or dict-view, with a <em>built-in protocol for visiting each element in a certain order</em>.
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
In a nutshell: Most commonly, <strong>a generator is a lazy, incrementally-pending list</strong>, and <strong><code>yield</code> statements allow you to use function notation to program the list values</strong> the generator should incrementally spit out. <strong>Furthermore, advanced usage lets you use generators as coroutines (see below).</strong>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">generator = myYieldingFunction(...) <span class="hljs-comment"># basically a list (but lazy)</span>
|
||
x = <span class="hljs-built_in">list</span>(generator) <span class="hljs-comment"># evaluate every element into a list</span>
|
||
|
||
generator
|
||
v
|
||
[x[<span class="hljs-number">0</span>], ..., ???]
|
||
|
||
generator
|
||
v
|
||
[x[<span class="hljs-number">0</span>], x[<span class="hljs-number">1</span>], ..., ???]
|
||
|
||
generator
|
||
v
|
||
[x[<span class="hljs-number">0</span>], x[<span class="hljs-number">1</span>], x[<span class="hljs-number">2</span>], ..., ???]
|
||
|
||
StopIteration exception
|
||
[x[<span class="hljs-number">0</span>], x[<span class="hljs-number">1</span>], x[<span class="hljs-number">2</span>]] done
|
||
</code></pre>
|
||
<p>
|
||
Basically, whenever the <code>yield</code> statement is encountered, the function pauses and saves its state, then emits "the next return value in the 'list'" according to the python iterator protocol (to some syntactic construct like a for-loop that repeatedly calls <code>next()</code> and catches a <code>StopIteration</code> exception, etc.). You might have encountered generators with <a href="https://www.python.org/dev/peps/pep-0289/" rel="noreferrer">generator expressions</a>; generator functions are more powerful because you can pass arguments back into the paused generator function, using them to implement coroutines. More on that later.
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
Basic Example ('list')
|
||
</h2>
|
||
<p>
|
||
Let's define a function <code>makeRange</code> that's just like Python's <code>range</code>. Calling <code>makeRange(n)</code> RETURNS A GENERATOR:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">makeRange</span>(<span class="hljs-params">n</span>):
|
||
<span class="hljs-comment"># return 0,1,2,...,n-1</span>
|
||
i = <span class="hljs-number">0</span>
|
||
<span class="hljs-keyword">while</span> i < n:
|
||
<span class="hljs-keyword">yield</span> i
|
||
i += <span class="hljs-number">1</span>
|
||
|
||
<span class="hljs-meta">>>> </span>makeRange(<span class="hljs-number">5</span>)
|
||
<generator <span class="hljs-built_in">object</span> makeRange at <span class="hljs-number">0x19e4aa0</span>>
|
||
</code></pre>
|
||
<p>
|
||
To force the generator to immediately return its pending values, you can pass it into <code>list()</code> (just like you could any iterable):
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(makeRange(<span class="hljs-number">5</span>))
|
||
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
</code></pre>
|
||
<hr />
|
||
<h2>
|
||
Comparing example to "just returning a list"
|
||
</h2>
|
||
<p>
|
||
The above example can be thought of as merely creating a list which you append to and return:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-comment"># return a list # # return a generator</span>
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">makeRange</span>(<span class="hljs-params">n</span>): <span class="hljs-comment"># def makeRange(n):</span>
|
||
<span class="hljs-string">"""return [0,1,2,...,n-1]"""</span> <span class="hljs-comment"># """return 0,1,2,...,n-1"""</span>
|
||
TO_RETURN = [] <span class="hljs-comment"># </span>
|
||
i = <span class="hljs-number">0</span> <span class="hljs-comment"># i = 0</span>
|
||
<span class="hljs-keyword">while</span> i < n: <span class="hljs-comment"># while i < n:</span>
|
||
TO_RETURN += [i] <span class="hljs-comment"># yield i</span>
|
||
i += <span class="hljs-number">1</span> <span class="hljs-comment"># i += 1</span>
|
||
<span class="hljs-keyword">return</span> TO_RETURN <span class="hljs-comment"># </span>
|
||
|
||
<span class="hljs-meta">>>> </span>makeRange(<span class="hljs-number">5</span>)
|
||
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
</code></pre>
|
||
<p>
|
||
There is one major difference, though; see the last section.
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
How you might use generators
|
||
</h2>
|
||
<p>
|
||
An iterable is the last part of a list comprehension, and all generators are iterable, so they're often used like so:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-comment"># < ITERABLE ></span>
|
||
<span class="hljs-meta">>>> </span>[x+<span class="hljs-number">10</span> <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> makeRange(<span class="hljs-number">5</span>)]
|
||
[<span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>, <span class="hljs-number">13</span>, <span class="hljs-number">14</span>]
|
||
</code></pre>
|
||
<p>
|
||
To get a better feel for generators, you can play around with the <code>itertools</code> module (be sure to use <code>chain.from_iterable</code> rather than <code>chain</code> when warranted). For example, you might even use generators to implement infinitely-long lazy lists like <code>itertools.count()</code>. You could implement your own <code>def enumerate(iterable): zip(count(), iterable)</code>, or alternatively do so with the <code>yield</code> keyword in a while-loop.
|
||
</p>
|
||
<p>
|
||
Please note: generators can actually be used for many more things, such as <a href="http://www.dabeaz.com/coroutines/index.html" rel="noreferrer">implementing coroutines</a> or non-deterministic programming or other elegant things. However, the "lazy lists" viewpoint I present here is the most common use you will find.
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
Behind the scenes
|
||
</h2>
|
||
<p>
|
||
This is how the "Python iteration protocol" works. That is, what is going on when you do <code>list(makeRange(5))</code>. This is what I describe earlier as a "lazy, incremental list".
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>x=<span class="hljs-built_in">iter</span>(<span class="hljs-built_in">range</span>(<span class="hljs-number">5</span>))
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x) <span class="hljs-comment"># calls x.__next__(); x.next() is deprecated</span>
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
|
||
<span class="hljs-number">2</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
|
||
<span class="hljs-number">3</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
|
||
<span class="hljs-number">4</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">next</span>(x)
|
||
Traceback (most recent call last):
|
||
File <span class="hljs-string">"<stdin>"</span>, line <span class="hljs-number">1</span>, <span class="hljs-keyword">in</span> <module>
|
||
StopIteration
|
||
</code></pre>
|
||
<p>
|
||
The built-in function <code>next()</code> just calls the objects <code>.__next__()</code> function, which is a part of the "iteration protocol" and is found on all iterators. You can manually use the <code>next()</code> function (and other parts of the iteration protocol) to implement fancy things, usually at the expense of readability, so try to avoid doing that...
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
Coroutines
|
||
</h2>
|
||
<p>
|
||
<a href="https://www.python.org/dev/peps/pep-0342/" rel="noreferrer">Coroutine</a> example:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">interactiveProcedure</span>():
|
||
userResponse = <span class="hljs-keyword">yield</span> makeQuestionWebpage()
|
||
<span class="hljs-built_in">print</span>(<span class="hljs-string">'user response:'</span>, userResponse)
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'success'</span>
|
||
|
||
coroutine = interactiveProcedure()
|
||
webFormData = <span class="hljs-built_in">next</span>(coroutine) <span class="hljs-comment"># same as .send(None)</span>
|
||
userResponse = serveWebForm(webFormData)
|
||
|
||
<span class="hljs-comment"># ...at some point later on web form submit...</span>
|
||
|
||
successStatus = coroutine.send(userResponse)
|
||
</code></pre>
|
||
<p>
|
||
A coroutine (generators which generally accept input via the <code>yield</code> keyword e.g. <code>nextInput = yield nextOutput</code>, as a form of two-way communication) is basically a computation which is allowed to pause itself and request input (e.g. to what it should do next). When the coroutine pauses itself (when the running coroutine eventually hits a <code>yield</code> keyword), the computation is paused and control is inverted (yielded) back to the 'calling' function (the frame which requested the <code>next</code> value of the computation). The paused generator/coroutine remains paused until another invoking function (possibly a different function/context) requests the next value to unpause it (usually passing input data to direct the paused logic interior to the coroutine's code).
|
||
</p>
|
||
<p>
|
||
<strong>You can think of python coroutines as lazy incrementally-pending lists, where the next element doesn't just depend on the previous computation, but also on input you may opt to inject during the generation process.</strong>
|
||
</p>
|
||
<hr />
|
||
<h2>
|
||
Minutiae
|
||
</h2>
|
||
<p>
|
||
Normally, most people would not care about the following distinctions and probably want to stop reading here.
|
||
</p>
|
||
<p>
|
||
In Python-speak, an <em>iterable</em> is any object which "understands the concept of a for-loop" like a list <code>[1,2,3]</code>, and an <em>iterator</em> is a specific instance of the requested for-loop like <code>[1,2,3].__iter__()</code>. A <em>generator</em> is exactly the same as any iterator, except for the way it was written (with function syntax).
|
||
</p>
|
||
<p>
|
||
When you request an iterator from a list, it creates a new iterator. However, when you request an iterator from an iterator (which you would rarely do), it just gives you a copy of itself.
|
||
</p>
|
||
<p>
|
||
Thus, in the unlikely event that you are failing to do something like this...
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">> x = myRange(<span class="hljs-number">5</span>)
|
||
> <span class="hljs-built_in">list</span>(x)
|
||
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
|
||
> <span class="hljs-built_in">list</span>(x)
|
||
[]
|
||
</code></pre>
|
||
<p>
|
||
... then remember that a generator is an <em>iterator</em>; that is, it is one-time-use. If you want to reuse it, you should call <code>myRange(...)</code> again. If you need to use the result twice, convert the result to a list and store it in a variable <code>x = list(myRange(5))</code>. Those who absolutely need to clone a generator (for example, who are doing terrifyingly hackish metaprogramming) can use <a href="https://docs.python.org/2/library/itertools.html#itertools.tee" rel="noreferrer"><code>itertools.tee</code></a> (<a href="https://docs.python.org/3/library/itertools.html#itertools.tee" rel="noreferrer">still works in Python 3</a>) if absolutely necessary, since the <a href="https://www.python.org/dev/peps/pep-0323/" rel="noreferrer">copyable iterator Python PEP standards proposal</a> has been deferred.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="6400990">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/6400990" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-4" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-4">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-4">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-4" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/6400990/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-6400990" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-o7bilow4">Follow</button>
|
||
<div id="--stacks-s-tooltip-o7bilow4" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/6400990/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2022-10-01 12:07:30Z" class="relativetime">Oct 1 at 12:07</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2011-06-19 06:33:58Z" class="relativetime">Jun 19, 2011 at 6:33</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/711085/ninjagecko">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/fabf3436107ffee76255957a7732d0f1?s=64&d=identicon&r=PG" alt="ninjagecko's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/711085/ninjagecko">ninjagecko</a><span class="d-none" itemprop="name">ninjagecko</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 85,912" dir="ltr">85.9k</span><span title="24 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">24</span></span><span class="v-visible-sr">24 gold badges</span><span title="134 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">134</span></span><span class="v-visible-sr">134 silver badges</span><span title="143 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">143</span></span><span class="v-visible-sr">143 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-6400990" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="6400990" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-6400990" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="31042491" id="31042491"></a>
|
||
<div id="answer-31042491" class="answer js-answer" data-answerid="31042491" data-parentid="231767" data-score="527" data-position-on-page="5" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="31042491">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-aw875gic"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-aw875gic" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="527">
|
||
527
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-6804e4ql"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-6804e4ql" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-31042491" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="31042491" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-rmnh8nm1"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-rmnh8nm1" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/31042491/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-80cbfvhw"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-80cbfvhw" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<blockquote>
|
||
<p>
|
||
<strong>What does the <code>yield</code> keyword do in Python?</strong>
|
||
</p>
|
||
</blockquote>
|
||
<h1>
|
||
Answer Outline/Summary
|
||
</h1>
|
||
<ul>
|
||
<li>A function with <a href="https://docs.python.org/reference/expressions.html#yieldexpr" rel="nofollow noreferrer"><strong><code>yield</code></strong></a>, when called, <strong>returns a <a href="https://docs.python.org/2/tutorial/classes.html#generators" rel="nofollow noreferrer">Generator</a>.</strong>
|
||
</li>
|
||
<li>Generators are iterators because they implement the <a href="https://docs.python.org/2/library/stdtypes.html#iterator-types" rel="nofollow noreferrer"><strong>iterator protocol</strong></a>, so you can iterate over them.
|
||
</li>
|
||
<li>A generator can also be <strong>sent information</strong>, making it conceptually a <strong>coroutine</strong>.
|
||
</li>
|
||
<li>In Python 3, you can <strong>delegate</strong> from one generator to another in both directions with <strong><code>yield from</code></strong>.
|
||
</li>
|
||
<li>(Appendix critiques a couple of answers, including the top one, and discusses the use of <code>return</code> in a generator.)
|
||
</li>
|
||
</ul>
|
||
<h1>
|
||
Generators:
|
||
</h1>
|
||
<p>
|
||
<strong><code>yield</code></strong> is only legal inside of a function definition, and <strong>the inclusion of <code>yield</code> in a function definition makes it return a generator.</strong>
|
||
</p>
|
||
<p>
|
||
The idea for generators comes from other languages (see footnote 1) with varying implementations. In Python's Generators, the execution of the code is <a href="https://docs.python.org/3.5/glossary.html#term-generator-iterator" rel="nofollow noreferrer">frozen</a> at the point of the yield. When the generator is called (methods are discussed below) execution resumes and then freezes at the next yield.
|
||
</p>
|
||
<p>
|
||
<code>yield</code> provides an easy way of <a href="https://docs.python.org/2/library/stdtypes.html#generator-types" rel="nofollow noreferrer">implementing the iterator protocol</a>, defined by the following two methods: <code>__iter__</code> and <code>__next__</code>. Both of those methods make an object an iterator that you could type-check with the <code>Iterator</code> Abstract Base Class from the <code>collections</code> module.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">func</span>():
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'I am'</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'a generator!'</span>
|
||
</code></pre>
|
||
<p>
|
||
Let's do some introspection:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">type</span>(func) <span class="hljs-comment"># A function with yield is still a function</span>
|
||
<<span class="hljs-built_in">type</span> <span class="hljs-string">'function'</span>>
|
||
<span class="hljs-meta">>>> </span>gen = func()
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">type</span>(gen) <span class="hljs-comment"># but it returns a generator</span>
|
||
<<span class="hljs-built_in">type</span> <span class="hljs-string">'generator'</span>>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">hasattr</span>(gen, <span class="hljs-string">'__iter__'</span>) <span class="hljs-comment"># that's an iterable</span>
|
||
<span class="hljs-literal">True</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">hasattr</span>(gen, <span class="hljs-string">'__next__'</span>) <span class="hljs-comment"># and with .__next__</span>
|
||
<span class="hljs-literal">True</span> <span class="hljs-comment"># implements the iterator protocol.</span>
|
||
</code></pre>
|
||
<p>
|
||
The generator type is a sub-type of iterator:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">from</span> types <span class="hljs-keyword">import</span> GeneratorType
|
||
<span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Iterator
|
||
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">issubclass</span>(GeneratorType, Iterator)
|
||
<span class="hljs-literal">True</span>
|
||
</code></pre>
|
||
<p>
|
||
And if necessary, we can type-check like this:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">isinstance</span>(gen, GeneratorType)
|
||
<span class="hljs-literal">True</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">isinstance</span>(gen, Iterator)
|
||
<span class="hljs-literal">True</span>
|
||
</code></pre>
|
||
<p>
|
||
A feature of an <code>Iterator</code> <a href="https://docs.python.org/2/glossary.html#term-iterator" rel="nofollow noreferrer">is that once exhausted</a>, you can't reuse or reset it:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(gen)
|
||
[<span class="hljs-string">'I am'</span>, <span class="hljs-string">'a generator!'</span>]
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(gen)
|
||
[]
|
||
</code></pre>
|
||
<p>
|
||
You'll have to make another if you want to use its functionality again (see footnote 2):
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(func())
|
||
[<span class="hljs-string">'I am'</span>, <span class="hljs-string">'a generator!'</span>]
|
||
</code></pre>
|
||
<p>
|
||
One can yield data programmatically, for example:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">func</span>(<span class="hljs-params">an_iterable</span>):
|
||
<span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> an_iterable:
|
||
<span class="hljs-keyword">yield</span> item
|
||
</code></pre>
|
||
<p>
|
||
The above simple generator is also equivalent to the below - as of Python 3.3 you can use <a href="https://www.python.org/dev/peps/pep-0380/" rel="nofollow noreferrer"><code>yield from</code></a>:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">func</span>(<span class="hljs-params">an_iterable</span>):
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> an_iterable
|
||
</code></pre>
|
||
<p>
|
||
However, <code>yield from</code> also allows for delegation to subgenerators, which will be explained in the following section on cooperative delegation with sub-coroutines.
|
||
</p>
|
||
<h1>
|
||
Coroutines:
|
||
</h1>
|
||
<p>
|
||
<code>yield</code> forms an expression that allows data to be sent into the generator (see footnote 3)
|
||
</p>
|
||
<p>
|
||
Here is an example, take note of the <code>received</code> variable, which will point to the data that is sent to the generator:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">bank_account</span>(<span class="hljs-params">deposited, interest_rate</span>):
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
calculated_interest = interest_rate * deposited
|
||
received = <span class="hljs-keyword">yield</span> calculated_interest
|
||
<span class="hljs-keyword">if</span> received:
|
||
deposited += received
|
||
|
||
|
||
<span class="hljs-meta">>>> </span>my_account = bank_account(<span class="hljs-number">1000</span>, <span class="hljs-number">.05</span>)
|
||
</code></pre>
|
||
<p>
|
||
First, we must queue up the generator with the builtin function, <a href="https://docs.python.org/2/library/functions.html#next" rel="nofollow noreferrer"><code>next</code></a>. It will call the appropriate <code>next</code> or <code>__next__</code> method, depending on the version of Python you are using:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>first_year_interest = <span class="hljs-built_in">next</span>(my_account)
|
||
<span class="hljs-meta">>>> </span>first_year_interest
|
||
<span class="hljs-number">50.0</span>
|
||
</code></pre>
|
||
<p>
|
||
And now we can send data into the generator. (<a href="https://www.python.org/dev/peps/pep-0342/#specification-sending-values-into-generators" rel="nofollow noreferrer">Sending <code>None</code> is the same as calling <code>next</code></a>.) :
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>next_year_interest = my_account.send(first_year_interest + <span class="hljs-number">1000</span>)
|
||
<span class="hljs-meta">>>> </span>next_year_interest
|
||
<span class="hljs-number">102.5</span>
|
||
</code></pre>
|
||
<h2>
|
||
Cooperative Delegation to Sub-Coroutine with <code>yield from</code>
|
||
</h2>
|
||
<p>
|
||
Now, recall that <code>yield from</code> is available in Python 3. This allows us to delegate coroutines to a subcoroutine:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">money_manager</span>(<span class="hljs-params">expected_rate</span>):
|
||
<span class="hljs-comment"># must receive deposited value from .send():</span>
|
||
under_management = <span class="hljs-keyword">yield</span> <span class="hljs-comment"># yield None to start.</span>
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-keyword">try</span>:
|
||
additional_investment = <span class="hljs-keyword">yield</span> expected_rate * under_management
|
||
<span class="hljs-keyword">if</span> additional_investment:
|
||
under_management += additional_investment
|
||
<span class="hljs-keyword">except</span> GeneratorExit:
|
||
<span class="hljs-string">'''TODO: write function to send unclaimed funds to state'''</span>
|
||
<span class="hljs-keyword">raise</span>
|
||
<span class="hljs-keyword">finally</span>:
|
||
<span class="hljs-string">'''TODO: write function to mail tax info to client'''</span>
|
||
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">investment_account</span>(<span class="hljs-params">deposited, manager</span>):
|
||
<span class="hljs-string">'''very simple model of an investment account that delegates to a manager'''</span>
|
||
<span class="hljs-comment"># must queue up manager:</span>
|
||
<span class="hljs-built_in">next</span>(manager) <span class="hljs-comment"># <- same as manager.send(None)</span>
|
||
<span class="hljs-comment"># This is where we send the initial deposit to the manager:</span>
|
||
manager.send(deposited)
|
||
<span class="hljs-keyword">try</span>:
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> manager
|
||
<span class="hljs-keyword">except</span> GeneratorExit:
|
||
<span class="hljs-keyword">return</span> manager.close() <span class="hljs-comment"># delegate?</span>
|
||
</code></pre>
|
||
<p>
|
||
And now we can delegate functionality to a sub-generator and it can be used by a generator just as above:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">my_manager = money_manager(<span class="hljs-number">.06</span>)
|
||
my_account = investment_account(<span class="hljs-number">1000</span>, my_manager)
|
||
first_year_return = <span class="hljs-built_in">next</span>(my_account) <span class="hljs-comment"># -> 60.0</span>
|
||
</code></pre>
|
||
<p>
|
||
Now simulate adding another 1,000 to the account plus the return on the account (60.0):
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">next_year_return = my_account.send(first_year_return + <span class="hljs-number">1000</span>)
|
||
next_year_return <span class="hljs-comment"># 123.6</span>
|
||
</code></pre>
|
||
<p>
|
||
You can read more about the precise semantics of <code>yield from</code> in <a href="https://www.python.org/dev/peps/pep-0380/#formal-semantics" rel="nofollow noreferrer">PEP 380.</a>
|
||
</p>
|
||
<h2>
|
||
Other Methods: close and throw
|
||
</h2>
|
||
<p>
|
||
The <code>close</code> method raises <code>GeneratorExit</code> at the point the function execution was frozen. This will also be called by <code>__del__</code> so you can put any cleanup code where you handle the <code>GeneratorExit</code>:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">my_account.close()
|
||
</code></pre>
|
||
<p>
|
||
You can also throw an exception which can be handled in the generator or propagated back to the user:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">import</span> sys
|
||
<span class="hljs-keyword">try</span>:
|
||
<span class="hljs-keyword">raise</span> ValueError
|
||
<span class="hljs-keyword">except</span>:
|
||
my_manager.throw(*sys.exc_info())
|
||
</code></pre>
|
||
<p>
|
||
Raises:
|
||
</p>
|
||
<pre class="lang-none s-code-block"><code>Traceback (most recent call last):
|
||
File "<stdin>", line 4, in <module>
|
||
File "<stdin>", line 6, in money_manager
|
||
File "<stdin>", line 2, in <module>
|
||
ValueError
|
||
</code></pre>
|
||
<h1>
|
||
Conclusion
|
||
</h1>
|
||
<p>
|
||
I believe I have covered all aspects of the following question:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
<strong>What does the <code>yield</code> keyword do in Python?</strong>
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
It turns out that <code>yield</code> does a lot. I'm sure I could add even more thorough examples to this. If you want more or have some constructive criticism, let me know by commenting below.
|
||
</p>
|
||
<hr />
|
||
<h1>
|
||
Appendix:
|
||
</h1>
|
||
<h2>
|
||
Critique of the Top/Accepted Answer**
|
||
</h2>
|
||
<ul>
|
||
<li>It is confused on what makes an <strong>iterable</strong>, just using a list as an example. See my references above, but in summary: an <strong>iterable</strong> has an <code>__iter__</code> method returning an <strong>iterator</strong>. An <strong>iterator</strong> additionally provides a <code>.__next__</code> method, which is implicitly called by <code>for</code> loops until it raises <code>StopIteration</code>, and once it does raise <code>StopIteration</code>, it will continue to do so.
|
||
</li>
|
||
<li>It then uses a generator expression to describe what a generator is. Since a generator expression is simply a convenient way to create an <strong>iterator</strong>, it only confuses the matter, and we still have not yet gotten to the <code>yield</code> part.
|
||
</li>
|
||
<li>In <strong>Controlling a generator exhaustion</strong> he calls the <code>.next</code> method (which only works in Python 2), when instead he should use the builtin function, <code>next</code>. Calling <code>next(obj)</code> would be an appropriate layer of indirection, because his code does not work in Python 3.
|
||
</li>
|
||
<li>Itertools? This was not relevant to what <code>yield</code> does at all.
|
||
</li>
|
||
<li>No discussion of the methods that <code>yield</code> provides along with the new functionality <code>yield from</code> in Python 3.
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
<strong>The top/accepted answer is a very incomplete answer.</strong>
|
||
</p>
|
||
<h2>
|
||
Critique of answer suggesting <code>yield</code> in a generator expression or comprehension.
|
||
</h2>
|
||
<p>
|
||
The grammar currently allows any expression in a list comprehension.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
|
||
(<span class="hljs-string">'='</span> (yield_expr|testlist_star_expr))*)
|
||
...
|
||
yield_expr: <span class="hljs-string">'yield'</span> [yield_arg]
|
||
yield_arg: <span class="hljs-string">'from'</span> test | testlist
|
||
</code></pre>
|
||
<p>
|
||
Since yield is an expression, it has been touted by some as interesting to use it in comprehensions or generator expression - in spite of citing no particularly good use-case.
|
||
</p>
|
||
<p>
|
||
The CPython core developers are <a href="https://mail.python.org/pipermail/python-dev/2017-January/147301.html" rel="nofollow noreferrer">discussing deprecating its allowance</a>. Here's a relevant post from the mailing list:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
On 30 January 2017 at 19:05, Brett Cannon wrote:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
On Sun, 29 Jan 2017 at 16:39 Craig Rodrigues wrote:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
I'm OK with either approach. Leaving things the way they are in Python 3 is no good, IMHO.
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
My vote is it be a SyntaxError since you're not getting what you expect from the syntax.
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
I'd agree that's a sensible place for us to end up, as any code relying on the current behaviour is really too clever to be maintainable.
|
||
</p>
|
||
<p>
|
||
In terms of getting there, we'll likely want:
|
||
</p>
|
||
<ul>
|
||
<li>SyntaxWarning or DeprecationWarning in 3.7
|
||
</li>
|
||
<li>Py3k warning in 2.7.x
|
||
</li>
|
||
<li>SyntaxError in 3.8
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
Cheers, Nick.
|
||
</p>
|
||
<p>
|
||
-- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
Further, there is an <a href="http://bugs.python.org/issue10544" rel="nofollow noreferrer">outstanding issue (10544)</a> which seems to be pointing in the direction of this <em>never</em> being a good idea (PyPy, a Python implementation written in Python, is already raising syntax warnings.)
|
||
</p>
|
||
<p>
|
||
Bottom line, until the developers of CPython tell us otherwise: <strong>Don't put <code>yield</code> in a generator expression or comprehension.</strong>
|
||
</p>
|
||
<h2>
|
||
The <code>return</code> statement in a generator
|
||
</h2>
|
||
<p>
|
||
In <a href="https://docs.python.org/3/reference/simple_stmts.html#the-return-statement" rel="nofollow noreferrer">Python 3</a>:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
In a generator function, the <code>return</code> statement indicates that the generator is done and will cause <code>StopIteration</code> to be raised. The returned value (if any) is used as an argument to construct <code>StopIteration</code> and becomes the <code>StopIteration.value</code> attribute.
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
<sub>Historical note, in <a href="https://docs.python.org/2/reference/simple_stmts.html#the-return-statement" rel="nofollow noreferrer">Python 2</a>: "In a generator function, the <code>return</code> statement is not allowed to include an <code>expression_list</code>. In that context, a bare <code>return</code> indicates that the generator is done and will cause <code>StopIteration</code> to be raised." An <code>expression_list</code> is basically any number of expressions separated by commas - essentially, in Python 2, you can stop the generator with <code>return</code>, but you can't return a value.</sub>
|
||
</p>
|
||
<h2>
|
||
Footnotes
|
||
</h2>
|
||
<ol>
|
||
<li>
|
||
<p>
|
||
<sub>The languages CLU, Sather, and Icon were referenced in the proposal to introduce the concept of generators to Python. The general idea is that a function can maintain internal state and yield intermediate data points on demand by the user. This promised to be <a href="https://www.python.org/dev/peps/pep-0255/" rel="nofollow noreferrer">superior in performance to other approaches, including Python threading</a>, which isn't even available on some systems.</sub>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<sub>This means, for example, that <code>range</code> objects aren't <code>Iterator</code>s, even though they are iterable, because they can be reused. Like lists, their <code>__iter__</code> methods return iterator objects.</sub>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<sub><code>yield</code> was originally introduced as a statement, meaning that it could only appear at the beginning of a line in a code block. Now <code>yield</code> creates a yield expression. <a href="https://docs.python.org/2/reference/simple_stmts.html#grammar-token-yield_stmt" rel="nofollow noreferrer">https://docs.python.org/2/reference/simple_stmts.html#grammar-token-yield_stmt</a> This change was <a href="https://www.python.org/dev/peps/pep-0342/#specification-sending-values-into-generators" rel="nofollow noreferrer">proposed</a> to allow a user to send data into the generator just as one might receive it. To send data, one must be able to assign it to something, and for that, a statement just won't work.</sub>
|
||
</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="31042491">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/31042491" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-5" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-5">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-5">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-5" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/31042491/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-31042491" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-yzy8b4zc">Follow</button>
|
||
<div id="--stacks-s-tooltip-yzy8b4zc" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/31042491/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2022-10-26 08:26:51Z" class="relativetime">Oct 26 at 8:26</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2015-06-25 06:11:11Z" class="relativetime">Jun 25, 2015 at 6:11</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/541136/russia-must-remove-putin">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/wftMn.jpg?s=64&g=1" alt="Russia Must Remove Putin's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/541136/russia-must-remove-putin">Russia Must Remove Putin</a><span class="mod-flair mtn2" title="Moderator">♦</span><span class="d-none" itemprop="name">Russia Must Remove Putin</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 355,545" dir="ltr">356k</span><span title="85 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">85</span></span><span class="v-visible-sr">85 gold badges</span><span title="395 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">395</span></span><span class="v-visible-sr">395 silver badges</span><span title="329 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">329</span></span><span class="v-visible-sr">329 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-31042491" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="31042491" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-31042491" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="231778" id="231778"></a>
|
||
<div id="answer-231778" class="answer js-answer" data-answerid="231778" data-parentid="231767" data-score="432" data-position-on-page="6" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="231778">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-dkd4s5gt"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-dkd4s5gt" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="432">
|
||
432
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-37nb5mpe"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-37nb5mpe" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-231778" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="231778" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-jh6lc3uu"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-jh6lc3uu" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/231778/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-gavg8jbv"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-gavg8jbv" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
<code>yield</code> is just like <code>return</code> - it returns whatever you tell it to (as a generator). The difference is that the next time you call the generator, execution starts from the last call to the <code>yield</code> statement. Unlike return, <strong>the stack frame is not cleaned up when a yield occurs, however control is transferred back to the caller, so its state will resume the next time the function is called.</strong>
|
||
</p>
|
||
<p>
|
||
In the case of your code, the function <code>get_child_candidates</code> is acting like an iterator so that when you extend your list, it adds one element at a time to the new list.
|
||
</p>
|
||
<p>
|
||
<code>list.extend</code> calls an iterator until it's exhausted. In the case of the code sample you posted, it would be much clearer to just return a tuple and append that to the list.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="231778">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/231778" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-6" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-6">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-6">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-6" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/231778/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-231778" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-j11r952p">Follow</button>
|
||
<div id="--stacks-s-tooltip-j11r952p" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/231778/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2019-01-24 09:39:59Z" class="relativetime">Jan 24, 2019 at 9:39</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/3551483/fang">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/I4c4V.png?s=64&g=1" alt="Fang's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/3551483/fang">Fang</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,091</span><span title="4 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">4</span></span><span class="v-visible-sr">4 gold badges</span><span title="22 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">22</span></span><span class="v-visible-sr">22 silver badges</span><span title="40 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">40</span></span><span class="v-visible-sr">40 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-23 22:24:03Z" class="relativetime">Oct 23, 2008 at 22:24</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/8458/douglas-mayle">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/545f75612aa60a8acc211cc86348eb16?s=64&d=identicon&r=PG" alt="Douglas Mayle's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/8458/douglas-mayle">Douglas Mayle</a><span class="d-none" itemprop="name">Douglas Mayle</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 20,403" dir="ltr">20.4k</span><span title="8 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">8</span></span><span class="v-visible-sr">8 gold badges</span><span title="42 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">42</span></span><span class="v-visible-sr">42 silver badges</span><span title="57 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">57</span></span><span class="v-visible-sr">57 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">1</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-231778" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="231778" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-99470" class="comment js-comment" data-comment-id="99470" data-comment-owner-id="30153" data-comment-score="124">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="supernova">124</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">This is close, but not correct. Every time you call a function with a yield statement in it, it returns a brand new generator object. It's only when you call that generator's .next() method that execution resumes after the last yield.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/30153/kurosch" title="2,282 reputation" class="comment-user">kurosch</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment99470_231778" aria-label="Link to comment"><span title="2008-10-24 18:11:04Z, License: CC BY-SA 2.5" class="relativetime-clean">Oct 24, 2008 at 18:11</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-231778" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="232853" id="232853"></a>
|
||
<div id="answer-232853" class="answer js-answer" data-answerid="232853" data-parentid="231767" data-score="305" data-position-on-page="7" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="232853">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-tcadu27d"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-tcadu27d" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="305">
|
||
305
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-i75yubc5"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-i75yubc5" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-232853" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="232853" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-y4gh764r"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-y4gh764r" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/232853/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-02evf1ej"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-02evf1ej" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
There's one extra thing to mention: a function that yields doesn't actually have to terminate. I've written code like this:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">fib</span>():
|
||
last, cur = <span class="hljs-number">0</span>, <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-keyword">yield</span> cur
|
||
last, cur = cur, last + cur
|
||
</code></pre>
|
||
<p>
|
||
Then I can use it in other code like this:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> fib():
|
||
<span class="hljs-keyword">if</span> some_condition: <span class="hljs-keyword">break</span>
|
||
coolfuncs(f);
|
||
</code></pre>
|
||
<p>
|
||
It really helps simplify some problems, and makes some things easier to work with.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="232853">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/232853" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-7" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-7">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-7">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-7" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/232853/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-232853" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-85ago4dd">Follow</button>
|
||
<div id="--stacks-s-tooltip-85ago4dd" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/232853/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2013-04-21 15:42:14Z" class="relativetime">Apr 21, 2013 at 15:42</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-24 08:44:08Z" class="relativetime">Oct 24, 2008 at 8:44</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/15055/claudiu">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/7f71287b47b7189d11fe6d3fbc7ed2fe?s=64&d=identicon&r=PG" alt="Claudiu's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/15055/claudiu">Claudiu</a><span class="d-none" itemprop="name">Claudiu</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 219,584" dir="ltr">220k</span><span title="161 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">161</span></span><span class="v-visible-sr">161 gold badges</span><span title="471 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">471</span></span><span class="v-visible-sr">471 silver badges</span><span title="676 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">676</span></span><span class="v-visible-sr">676 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-232853" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="232853" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-232853" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="14404292" id="14404292"></a>
|
||
<div id="answer-14404292" class="answer js-answer" data-answerid="14404292" data-parentid="231767" data-score="296" data-position-on-page="8" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="14404292">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-dxl7gh7c"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-dxl7gh7c" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="296">
|
||
296
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-hmdo4dy5"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-hmdo4dy5" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-14404292" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="14404292" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-fbyw4aid"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-fbyw4aid" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/14404292/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-vbgn06re"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-vbgn06re" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
For those who prefer a minimal working example, meditate on this interactive Python session:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>():
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> <span class="hljs-number">1</span>
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> <span class="hljs-number">2</span>
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> <span class="hljs-number">3</span>
|
||
<span class="hljs-meta">... </span>
|
||
<span class="hljs-meta">>>> </span>g = f()
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> g:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-meta">... </span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">2</span>
|
||
<span class="hljs-number">3</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> g:
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(i)
|
||
<span class="hljs-meta">... </span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-comment"># Note that this time nothing was printed</span>
|
||
</code></pre>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="14404292">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/14404292" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-8" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-8">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-8">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-8" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/14404292/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-14404292" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-0egqhd3g">Follow</button>
|
||
<div id="--stacks-s-tooltip-0egqhd3g" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/14404292/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2020-02-02 22:09:19Z" class="relativetime">Feb 2, 2020 at 22:09</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2236185/oren">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/60974524abdef48ec912ed63aae0b71b?s=64&d=identicon&r=PG&f=1" alt="Oren's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/2236185/oren">Oren</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">4,087</span><span title="4 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">4</span></span><span class="v-visible-sr">4 gold badges</span><span title="33 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">33</span></span><span class="v-visible-sr">33 silver badges</span><span title="61 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">61</span></span><span class="v-visible-sr">61 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-01-18 17:25:17Z" class="relativetime">Jan 18, 2013 at 17:25</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1531346/daniel">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/b221edf01a1f65198d7c6e6cfd2e4e2b?s=64&d=identicon&r=PG" alt="Daniel's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1531346/daniel">Daniel</a><span class="d-none" itemprop="name">Daniel</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">3,206</span><span title="1 gold badge" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">1</span></span><span class="v-visible-sr">1 gold badge</span><span title="12 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">12</span></span><span class="v-visible-sr">12 silver badges</span><span title="3 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-14404292" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="14404292" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-14404292" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="36220775" id="36220775"></a>
|
||
<div id="answer-36220775" class="answer js-answer" data-answerid="36220775" data-parentid="231767" data-score="275" data-position-on-page="9" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="36220775">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-ikgul5rn"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-ikgul5rn" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="275">
|
||
275
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-12omg2td"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-12omg2td" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-36220775" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="36220775" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-htolkbuz"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-htolkbuz" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/36220775/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-u9jjr2sr"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-u9jjr2sr" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
<strong>TL;DR</strong>
|
||
</p>
|
||
<h1>
|
||
Instead of this:
|
||
</h1>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">square_list</span>(<span class="hljs-params">n</span>):
|
||
the_list = [] <span class="hljs-comment"># Replace</span>
|
||
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
|
||
y = x * x
|
||
the_list.append(y) <span class="hljs-comment"># these</span>
|
||
<span class="hljs-keyword">return</span> the_list <span class="hljs-comment"># lines</span>
|
||
</code></pre>
|
||
<h1>
|
||
do this:
|
||
</h1>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">square_yield</span>(<span class="hljs-params">n</span>):
|
||
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
|
||
y = x * x
|
||
<span class="hljs-keyword">yield</span> y <span class="hljs-comment"># with this one.</span>
|
||
</code></pre>
|
||
<p>
|
||
Whenever you find yourself building a list from scratch, <code>yield</code> each piece instead.
|
||
</p>
|
||
<p>
|
||
This was my first "aha" moment with yield.
|
||
</p>
|
||
<hr />
|
||
<p>
|
||
<code>yield</code> is a <a href="https://en.wikipedia.org/wiki/Syntactic_sugar" rel="noreferrer">sugary</a> way to say
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
build a series of stuff
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
Same behavior:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> square <span class="hljs-keyword">in</span> square_list(<span class="hljs-number">4</span>):
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(square)
|
||
...
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
<span class="hljs-number">9</span>
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> square <span class="hljs-keyword">in</span> square_yield(<span class="hljs-number">4</span>):
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(square)
|
||
...
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
<span class="hljs-number">9</span>
|
||
</code></pre>
|
||
<p>
|
||
Different behavior:
|
||
</p>
|
||
<p>
|
||
Yield is <strong>single-pass</strong>: you can only iterate through once. When a function has a yield in it we call it a <a href="https://stackoverflow.com/a/1756342/673991">generator function</a>. And an <a href="https://stackoverflow.com/a/9884501/673991">iterator</a> is what it returns. Those terms are revealing. We lose the convenience of a container, but gain the power of a series that's computed as needed, and arbitrarily long.
|
||
</p>
|
||
<p>
|
||
Yield is <strong>lazy</strong>, it puts off computation. A function with a yield in it <em>doesn't actually execute at all when you call it.</em> It returns an <a href="https://docs.python.org/3/reference/expressions.html#yieldexpr" rel="noreferrer">iterator object</a> that remembers where it left off. Each time you call <code>next()</code> on the iterator (this happens in a for-loop) execution inches forward to the next yield. <code>return</code> raises StopIteration and ends the series (this is the natural end of a for-loop).
|
||
</p>
|
||
<p>
|
||
Yield is <strong>versatile</strong>. Data doesn't have to be stored all together, it can be made available one at a time. It can be infinite.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">def</span> <span class="hljs-title function_">squares_all_of_them</span>():
|
||
<span class="hljs-meta">... </span> x = <span class="hljs-number">0</span>
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">yield</span> x * x
|
||
<span class="hljs-meta">... </span> x += <span class="hljs-number">1</span>
|
||
...
|
||
<span class="hljs-meta">>>> </span>squares = squares_all_of_them()
|
||
<span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">4</span>):
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(<span class="hljs-built_in">next</span>(squares))
|
||
...
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-number">4</span>
|
||
<span class="hljs-number">9</span>
|
||
</code></pre>
|
||
<hr />
|
||
<p>
|
||
If you need <strong>multiple passes</strong> and the series isn't too long, just call <code>list()</code> on it:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-built_in">list</span>(square_yield(<span class="hljs-number">4</span>))
|
||
[<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">4</span>, <span class="hljs-number">9</span>]
|
||
</code></pre>
|
||
<hr />
|
||
<p>
|
||
Brilliant choice of the word <code>yield</code> because <a href="https://www.google.com/search?q=yield+meaning" rel="noreferrer">both meanings</a> apply:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
<strong>yield</strong> — produce or provide (as in agriculture)
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
...provide the next data in the series.
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
<strong>yield</strong> — give way or relinquish (as in political power)
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
...relinquish CPU execution until the iterator advances.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="36220775">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/36220775" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-9" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-9">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-9">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-9" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/36220775/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-36220775" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-nj1hk0be">Follow</button>
|
||
<div id="--stacks-s-tooltip-nj1hk0be" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/36220775/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2019-01-04 15:30:21Z" class="relativetime">Jan 4, 2019 at 15:30</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2016-03-25 13:21:44Z" class="relativetime">Mar 25, 2016 at 13:21</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/673991/bob-stein">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/ShtRG.jpg?s=64&g=1" alt="Bob Stein's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/673991/bob-stein">Bob Stein</a><span class="d-none" itemprop="name">Bob Stein</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 15,215" dir="ltr">15.2k</span><span title="9 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">9</span></span><span class="v-visible-sr">9 gold badges</span><span title="80 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">80</span></span><span class="v-visible-sr">80 silver badges</span><span title="98 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">98</span></span><span class="v-visible-sr">98 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-36220775" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="36220775" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-36220775" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="14352675" id="14352675"></a>
|
||
<div id="answer-14352675" class="answer js-answer" data-answerid="14352675" data-parentid="231767" data-score="236" data-position-on-page="10" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="14352675">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-nugu7t7a"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-nugu7t7a" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="236">
|
||
236
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-231jw4yu"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-231jw4yu" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-14352675" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="14352675" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-r8bpne46"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-r8bpne46" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/14352675/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-a9s685w8"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-a9s685w8" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Yield gives you a generator.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">get_odd_numbers</span>(<span class="hljs-params">i</span>):
|
||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, i, <span class="hljs-number">2</span>)
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">yield_odd_numbers</span>(<span class="hljs-params">i</span>):
|
||
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, i, <span class="hljs-number">2</span>):
|
||
<span class="hljs-keyword">yield</span> x
|
||
foo = get_odd_numbers(<span class="hljs-number">10</span>)
|
||
bar = yield_odd_numbers(<span class="hljs-number">10</span>)
|
||
foo
|
||
[<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">9</span>]
|
||
bar
|
||
<generator <span class="hljs-built_in">object</span> yield_odd_numbers at <span class="hljs-number">0x1029c6f50</span>>
|
||
bar.<span class="hljs-built_in">next</span>()
|
||
<span class="hljs-number">1</span>
|
||
bar.<span class="hljs-built_in">next</span>()
|
||
<span class="hljs-number">3</span>
|
||
bar.<span class="hljs-built_in">next</span>()
|
||
<span class="hljs-number">5</span>
|
||
</code></pre>
|
||
<p>
|
||
As you can see, in the first case <code>foo</code> holds the entire list in memory at once. It's not a big deal for a list with 5 elements, but what if you want a list of 5 million? Not only is this a huge memory eater, it also costs a lot of time to build at the time that the function is called.
|
||
</p>
|
||
<p>
|
||
In the second case, <code>bar</code> just gives you a generator. A generator is an iterable--which means you can use it in a <code>for</code> loop, etc, but each value can only be accessed once. All the values are also not stored in memory at the same time; the generator object "remembers" where it was in the looping the last time you called it--this way, if you're using an iterable to (say) count to 50 billion, you don't have to count to 50 billion all at once and store the 50 billion numbers to count through.
|
||
</p>
|
||
<p>
|
||
Again, this is a pretty contrived example, you probably would use itertools if you really wanted to count to 50 billion. :)
|
||
</p>
|
||
<p>
|
||
This is the most simple use case of generators. As you said, it can be used to write efficient permutations, using yield to push things up through the call stack instead of using some sort of stack variable. Generators can also be used for specialized tree traversal, and all manner of other things.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="14352675">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/14352675" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-10" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-10">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-10">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-10" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/14352675/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-14352675" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-ivy0i85r">Follow</button>
|
||
<div id="--stacks-s-tooltip-ivy0i85r" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/14352675/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2019-03-13 06:04:08Z" class="relativetime">Mar 13, 2019 at 6:04</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/4502035/andreas">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/e38a1b21c3e83f9d10aaa56c93f6150a?s=64&d=identicon&r=PG&f=1" alt="Andreas's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/4502035/andreas">Andreas</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,395</span><span title="10 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">10</span></span><span class="v-visible-sr">10 gold badges</span><span title="20 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">20</span></span><span class="v-visible-sr">20 silver badges</span><span title="23 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">23</span></span><span class="v-visible-sr">23 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-01-16 06:42:09Z" class="relativetime">Jan 16, 2013 at 6:42</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1776798/rbansal">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/41ac86025923cf752ae6aa44f9db9a32?s=64&d=identicon&r=PG" alt="RBansal's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1776798/rbansal">RBansal</a><span class="d-none" itemprop="name">RBansal</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,369</span><span title="1 gold badge" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">1</span></span><span class="v-visible-sr">1 gold badge</span><span title="12 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">12</span></span><span class="v-visible-sr">12 silver badges</span><span title="3 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">1</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-14352675" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="14352675" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-97303895" class="comment js-comment" data-comment-id="97303895" data-comment-owner-id="1822164" data-comment-score="3">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="cool">3</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">Just a note - in Python 3, <code>range</code> also returns a generator instead of a list, so you'd also see a similar idea, except that <code>__repr__</code>/<code>__str__</code> are overridden to show a nicer result, in this case <code>range(1, 10, 2)</code>.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/1822164/itsnotalie" title="21,954 reputation" class="comment-user">It'sNotALie.</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment97303895_14352675" aria-label="Link to comment"><span title="2019-03-21 18:33:13Z, License: CC BY-SA 4.0" class="relativetime-clean">Mar 21, 2019 at 18:33</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-14352675" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="231788" id="231788"></a>
|
||
<div id="answer-231788" class="answer js-answer" data-answerid="231788" data-parentid="231767" data-score="235" data-position-on-page="11" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="231788">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-3imv2n9n"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-3imv2n9n" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="235">
|
||
235
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-c97p3acw"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-c97p3acw" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-231788" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="231788" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-x6puol4s"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-x6puol4s" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/231788/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-klmd32ga"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-klmd32ga" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
It's returning a generator. I'm not particularly familiar with Python, but I believe it's the same kind of thing as <a href="http://csharpindepth.com/Articles/Chapter11/StreamingAndIterators.aspx" rel="noreferrer">C#'s iterator blocks</a> if you're familiar with those.
|
||
</p>
|
||
<p>
|
||
The key idea is that the compiler/interpreter/whatever does some trickery so that as far as the caller is concerned, they can keep calling next() and it will keep returning values - <em>as if the generator method was paused</em>. Now obviously you can't really "pause" a method, so the compiler builds a state machine for you to remember where you currently are and what the local variables etc look like. This is much easier than writing an iterator yourself.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="231788">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/231788" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-11" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-11">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-11">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-11" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/231788/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-231788" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-8yo3ics2">Follow</button>
|
||
<div id="--stacks-s-tooltip-8yo3ics2" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/231788/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-10-31 08:42:59Z" class="relativetime">Oct 31, 2018 at 8:42</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-23 22:26:06Z" class="relativetime">Oct 23, 2008 at 22:26</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/22656/jon-skeet">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/6d8ebb117e8d83d74ea95fbdd0f87e13?s=64&d=identicon&r=PG" alt="Jon Skeet's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/22656/jon-skeet">Jon Skeet</a><span class="d-none" itemprop="name">Jon Skeet</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 1,369,994" dir="ltr">1.4m</span><span title="842 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">842</span></span><span class="v-visible-sr">842 gold badges</span><span title="9008 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">9008</span></span><span class="v-visible-sr">9008 silver badges</span><span title="9114 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">9114</span></span><span class="v-visible-sr">9114 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-231788" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="231788" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-231788" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="15814755" id="15814755"></a>
|
||
<div id="answer-15814755" class="answer js-answer" data-answerid="15814755" data-parentid="231767" data-score="207" data-position-on-page="12" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="15814755">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zcjdkmkf"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zcjdkmkf" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="207">
|
||
207
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-jdskg0oe"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-jdskg0oe" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-15814755" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="15814755" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-n48cxk8l"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-n48cxk8l" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/15814755/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-qzr393gk"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-qzr393gk" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
There is one type of answer that I don't feel has been given yet, among the many great answers that describe how to use generators. Here is the programming language theory answer:
|
||
</p>
|
||
<p>
|
||
The <code>yield</code> statement in Python returns a generator. A generator in Python is a function that returns <i>continuations</i> (and specifically a type of coroutine, but continuations represent the more general mechanism to understand what is going on).
|
||
</p>
|
||
<p>
|
||
Continuations in programming languages theory are a much more fundamental kind of computation, but they are not often used, because they are extremely hard to reason about and also very difficult to implement. But the idea of what a continuation is, is straightforward: it is the state of a computation that has not yet finished. In this state, the current values of variables, the operations that have yet to be performed, and so on, are saved. Then at some point later in the program the continuation can be invoked, such that the program's variables are reset to that state and the operations that were saved are carried out.
|
||
</p>
|
||
<p>
|
||
Continuations, in this more general form, can be implemented in two ways. In the <code>call/cc</code> way, the program's stack is literally saved and then when the continuation is invoked, the stack is restored.
|
||
</p>
|
||
<p>
|
||
In continuation passing style (CPS), continuations are just normal functions (only in languages where functions are first class) which the programmer explicitly manages and passes around to subroutines. In this style, program state is represented by closures (and the variables that happen to be encoded in them) rather than variables that reside somewhere on the stack. Functions that manage control flow accept continuation as arguments (in some variations of CPS, functions may accept multiple continuations) and manipulate control flow by invoking them by simply calling them and returning afterwards. A very simple example of continuation passing style is as follows:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">save_file</span>(<span class="hljs-params">filename</span>):
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">write_file_continuation</span>():
|
||
write_stuff_to_file(filename)
|
||
|
||
check_if_file_exists_and_user_wants_to_overwrite(write_file_continuation)
|
||
</code></pre>
|
||
<p>
|
||
In this (very simplistic) example, the programmer saves the operation of actually writing the file into a continuation (which can potentially be a very complex operation with many details to write out), and then passes that continuation (i.e, as a first-class closure) to another operator which does some more processing, and then calls it if necessary. (I use this design pattern a lot in actual GUI programming, either because it saves me lines of code or, more importantly, to manage control flow after GUI events trigger.)
|
||
</p>
|
||
<p>
|
||
The rest of this post will, without loss of generality, conceptualize continuations as CPS, because it is a hell of a lot easier to understand and read.
|
||
</p>
|
||
<p>
|
||
<br />
|
||
</p>
|
||
<p>
|
||
Now let's talk about generators in Python. Generators are a specific subtype of continuation. Whereas <strong>continuations are able in general to save the state of a <em>computation</em></strong> (i.e., the program's call stack), <strong>generators are only able to save the state of iteration over an <em>iterator</em></strong>. Although, this definition is slightly misleading for certain use cases of generators. For instance:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f</span>():
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">4</span>
|
||
</code></pre>
|
||
<p>
|
||
This is clearly a reasonable iterable whose behavior is well defined -- each time the generator iterates over it, it returns 4 (and does so forever). But it isn't probably the prototypical type of iterable that comes to mind when thinking of iterators (i.e., <code>for x in collection: do_something(x)</code>). This example illustrates the power of generators: if anything is an iterator, a generator can save the state of its iteration.
|
||
</p>
|
||
<p>
|
||
To reiterate: Continuations can save the state of a program's stack and generators can save the state of iteration. This means that continuations are more a lot powerful than generators, but also that generators are a lot, lot easier. They are easier for the language designer to implement, and they are easier for the programmer to use (if you have some time to burn, try to read and understand <a href="http://www.madore.org/~david/computers/callcc.html" rel="noreferrer">this page about continuations and call/cc</a>).
|
||
</p>
|
||
<p>
|
||
But you could easily implement (and conceptualize) generators as a simple, specific case of continuation passing style:
|
||
</p>
|
||
<p>
|
||
Whenever <code>yield</code> is called, it tells the function to return a continuation. When the function is called again, it starts from wherever it left off. So, in pseudo-pseudocode (i.e., not pseudocode, but not code) the generator's <code>next</code> method is basically as follows:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Generator</span>():
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self,iterable,generatorfun</span>):
|
||
self.next_continuation = <span class="hljs-keyword">lambda</span>:generatorfun(iterable)
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">next</span>(<span class="hljs-params">self</span>):
|
||
value, next_continuation = self.next_continuation()
|
||
self.next_continuation = next_continuation
|
||
<span class="hljs-keyword">return</span> value
|
||
</code></pre>
|
||
<p>
|
||
where the <code>yield</code> keyword is actually syntactic sugar for the real generator function, basically something like:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">generatorfun</span>(<span class="hljs-params">iterable</span>):
|
||
<span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(iterable) == <span class="hljs-number">0</span>:
|
||
<span class="hljs-keyword">raise</span> StopIteration
|
||
<span class="hljs-keyword">else</span>:
|
||
<span class="hljs-keyword">return</span> (iterable[<span class="hljs-number">0</span>], <span class="hljs-keyword">lambda</span>:generatorfun(iterable[<span class="hljs-number">1</span>:]))
|
||
</code></pre>
|
||
<p>
|
||
Remember that this is just pseudocode and the actual implementation of generators in Python is more complex. But as an exercise to understand what is going on, try to use continuation passing style to implement generator objects without use of the <code>yield</code> keyword.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="15814755">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/15814755" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-12" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-12">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-12">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-12" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/15814755/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-15814755" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-h544xiyy">Follow</button>
|
||
<div id="--stacks-s-tooltip-h544xiyy" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/15814755/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 10:25:32Z" class="relativetime">May 20, 2018 at 10:25</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-04-04 14:56:19Z" class="relativetime">Apr 4, 2013 at 14:56</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2040716/aestrivex">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/2f3c22034b5114aa94cd4505e000f6c7?s=64&d=identicon&r=PG" alt="aestrivex's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/2040716/aestrivex">aestrivex</a><span class="d-none" itemprop="name">aestrivex</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">5,010</span><span title="2 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">2</span></span><span class="v-visible-sr">2 gold badges</span><span title="25 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">25</span></span><span class="v-visible-sr">25 silver badges</span><span title="43 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">43</span></span><span class="v-visible-sr">43 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-15814755" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="15814755" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-15814755" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="232111" id="232111"></a>
|
||
<div id="answer-232111" class="answer js-answer" data-answerid="232111" data-parentid="231767" data-score="207" data-position-on-page="13" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="232111">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-65zra2fa"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-65zra2fa" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="207">
|
||
207
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-3fq2pjdn"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-3fq2pjdn" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-232111" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="232111" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-71gevv24"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-71gevv24" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/232111/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-dhgb3bk0"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-dhgb3bk0" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Here is an example in plain language. I will provide a correspondence between high-level human concepts to low-level Python concepts.
|
||
</p>
|
||
<p>
|
||
I want to operate on a sequence of numbers, but I don't want to bother my self with the creation of that sequence, I want only to focus on the operation I want to do. So, I do the following:
|
||
</p>
|
||
<ul>
|
||
<li>I call you and tell you that I want a sequence of numbers which are calculated in a specific way, and I let you know what the algorithm is.<br />
|
||
<b>This step corresponds to <code>def</code>ining the generator function, i.e. the function containing a <code>yield</code>.</b>
|
||
</li>
|
||
<li>Sometime later, I tell you, "OK, get ready to tell me the sequence of numbers".<br />
|
||
<b>This step corresponds to calling the generator function which returns a generator object.</b> Note that you don't tell me any numbers yet; you just grab your paper and pencil.
|
||
</li>
|
||
<li>I ask you, "tell me the next number", and you tell me the first number; after that, you wait for me to ask you for the next number. It's your job to remember where you were, what numbers you have already said, and what is the next number. I don't care about the details.<br />
|
||
<b>This step corresponds to calling <code>next(generator)</code> on the generator object.</b><br />
|
||
(In Python 2, <code>.next</code> was a method of the generator object; in Python 3, it is named <code>.__next__</code>, but the proper way to call it is using the builtin <code>next()</code> function just like <code>len()</code> and <code>.__len__</code>)
|
||
</li>
|
||
<li>… repeat previous step, until…
|
||
</li>
|
||
<li>eventually, you might come to an end. You don't tell me a number; you just shout, "hold your horses! I'm done! No more numbers!"<br />
|
||
<b>This step corresponds to the generator object ending its job, and raising a <code>StopIteration</code> exception.</b><br />
|
||
The generator function does not need to raise the exception. It's raised automatically when the function ends or issues a <code>return</code>.
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
This is what a generator does (a function that contains a <code>yield</code>); it starts executing on the first <code>next()</code>, pauses whenever it does a <code>yield</code>, and when asked for the <code>next()</code> value it continues from the point it was last. It fits perfectly by design with the iterator protocol of Python, which describes how to sequentially request values.
|
||
</p>
|
||
<p>
|
||
The most famous user of the iterator protocol is the <code>for</code> command in Python. So, whenever you do a:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> sequence:
|
||
</code></pre>
|
||
<p>
|
||
it doesn't matter if <code>sequence</code> is a list, a string, a dictionary or a generator <em>object</em> like described above; the result is the same: you read items off a sequence one by one.
|
||
</p>
|
||
<p>
|
||
Note that <code>def</code>ining a function which contains a <code>yield</code> keyword is not the only way to create a generator; it's just the easiest way to create one.
|
||
</p>
|
||
<p>
|
||
For more accurate information, read about <a href="http://docs.python.org/library/stdtypes.html#iterator-types" rel="noreferrer">iterator types</a>, the <a href="http://docs.python.org/reference/simple_stmts.html#yield" rel="noreferrer">yield statement</a> and <a href="http://docs.python.org/glossary.html#term-generator" rel="noreferrer">generators</a> in the Python documentation.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="232111">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/232111" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-13" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-13">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-13">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-13" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/232111/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-232111" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-bqde1ief">Follow</button>
|
||
<div id="--stacks-s-tooltip-bqde1ief" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/232111/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2022-01-17 10:21:02Z" class="relativetime">Jan 17 at 10:21</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2008-10-24 00:36:05Z" class="relativetime">Oct 24, 2008 at 0:36</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/6899/tzot">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/132aeb33251a1eddee3efc87633c0af1?s=64&d=identicon&r=PG" alt="tzot's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/6899/tzot">tzot</a><span class="d-none" itemprop="name">tzot</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 89,811" dir="ltr">89.8k</span><span title="29 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">29</span></span><span class="v-visible-sr">29 gold badges</span><span title="138 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">138</span></span><span class="v-visible-sr">138 silver badges</span><span title="202 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">202</span></span><span class="v-visible-sr">202 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-232111" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="232111" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-232111" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="21541902" id="21541902"></a>
|
||
<div id="answer-21541902" class="answer js-answer" data-answerid="21541902" data-parentid="231767" data-score="162" data-position-on-page="14" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="21541902">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-eyia8dh3"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-eyia8dh3" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="162">
|
||
162
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-4nzqs1c9"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-4nzqs1c9" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-21541902" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="21541902" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-kc924hol"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-kc924hol" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/21541902/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-dqh9yhhp"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-dqh9yhhp" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
While a lot of answers show why you'd use a <code>yield</code> to create a generator, there are more uses for <code>yield</code>. It's quite easy to make a coroutine, which enables the passing of information between two blocks of code. I won't repeat any of the fine examples that have already been given about using <code>yield</code> to create a generator.
|
||
</p>
|
||
<p>
|
||
To help understand what a <code>yield</code> does in the following code, you can use your finger to trace the cycle through any code that has a <code>yield</code>. Every time your finger hits the <code>yield</code>, you have to wait for a <code>next</code> or a <code>send</code> to be entered. When a <code>next</code> is called, you trace through the code until you hit the <code>yield</code>… the code on the right of the <code>yield</code> is evaluated and returned to the caller… then you wait. When <code>next</code> is called again, you perform another loop through the code. However, you'll note that in a coroutine, <code>yield</code> can also be used with a <code>send</code>… which will send a value from the caller <em>into</em> the yielding function. If a <code>send</code> is given, then <code>yield</code> receives the value sent, and spits it out the left hand side… then the trace through the code progresses until you hit the <code>yield</code> again (returning the value at the end, as if <code>next</code> was called).
|
||
</p>
|
||
<p>
|
||
For example:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span><span class="hljs-keyword">def</span> <span class="hljs-title function_">coroutine</span>():
|
||
<span class="hljs-meta">... </span> i = -<span class="hljs-number">1</span>
|
||
<span class="hljs-meta">... </span> <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-meta">... </span> i += <span class="hljs-number">1</span>
|
||
<span class="hljs-meta">... </span> val = (<span class="hljs-keyword">yield</span> i)
|
||
<span class="hljs-meta">... </span> <span class="hljs-built_in">print</span>(<span class="hljs-string">"Received %s"</span> % val)
|
||
...
|
||
<span class="hljs-meta">>>> </span>sequence = coroutine()
|
||
<span class="hljs-meta">>>> </span>sequence.<span class="hljs-built_in">next</span>()
|
||
<span class="hljs-number">0</span>
|
||
<span class="hljs-meta">>>> </span>sequence.<span class="hljs-built_in">next</span>()
|
||
Received <span class="hljs-literal">None</span>
|
||
<span class="hljs-number">1</span>
|
||
<span class="hljs-meta">>>> </span>sequence.send(<span class="hljs-string">'hello'</span>)
|
||
Received hello
|
||
<span class="hljs-number">2</span>
|
||
<span class="hljs-meta">>>> </span>sequence.close()
|
||
</code></pre>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="21541902">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/21541902" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-14" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-14">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-14">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-14" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/21541902/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-21541902" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-6b1rno1i">Follow</button>
|
||
<div id="--stacks-s-tooltip-6b1rno1i" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2014-02-04 02:27:35Z" class="relativetime">Feb 4, 2014 at 2:27</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2379433/mike-mckerns">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/197d2417f199b0b6f951ee62e627a1d8?s=64&d=identicon&r=PG" alt="Mike McKerns's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/2379433/mike-mckerns">Mike McKerns</a><span class="d-none" itemprop="name">Mike McKerns</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 32,142" dir="ltr">32.1k</span><span title="8 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">8</span></span><span class="v-visible-sr">8 gold badges</span><span title="114 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">114</span></span><span class="v-visible-sr">114 silver badges</span><span title="138 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">138</span></span><span class="v-visible-sr">138 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">1</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-21541902" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="21541902" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-55942433" class="comment js-comment" data-comment-id="55942433" data-comment-owner-id="1998076" data-comment-score="2">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="cool">2</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">Cute! A <a href="https://en.wikipedia.org/wiki/Trampoline_(computing)" rel="nofollow noreferrer">trampoline</a> (in the Lisp sense). Not often one sees those!</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/1998076/00prometheus" title="727 reputation" class="comment-user">00prometheus</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment55942433_21541902" aria-label="Link to comment"><span title="2015-12-04 18:31:17Z, License: CC BY-SA 3.0" class="relativetime-clean">Dec 4, 2015 at 18:31</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-21541902" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="24944096" id="24944096"></a>
|
||
<div id="answer-24944096" class="answer js-answer" data-answerid="24944096" data-parentid="231767" data-score="158" data-position-on-page="15" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="24944096">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zc163wf6"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zc163wf6" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="158">
|
||
158
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zcwt3346"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zcwt3346" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-24944096" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="24944096" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-q9qyrvfs"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-q9qyrvfs" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/24944096/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-sodtru1h"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-sodtru1h" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
There is another <code>yield</code> use and meaning (since Python 3.3):
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">yield</span> <span class="hljs-keyword">from</span> <expr>
|
||
</code></pre>
|
||
<p>
|
||
From <em><a href="http://www.python.org/dev/peps/pep-0380/" rel="noreferrer">PEP 380 -- Syntax for Delegating to a Subgenerator</a></em>:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
A syntax is proposed for a generator to delegate part of its operations to another generator. This allows a section of code containing 'yield' to be factored out and placed in another generator. Additionally, the subgenerator is allowed to return with a value, and the value is made available to the delegating generator.
|
||
</p>
|
||
<p>
|
||
The new syntax also opens up some opportunities for optimisation when one generator re-yields values produced by another.
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
Moreover <a href="https://www.python.org/dev/peps/pep-0492/" rel="noreferrer">this</a> will introduce (since Python 3.5):
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">new_coroutine</span>(<span class="hljs-params">data</span>):
|
||
...
|
||
<span class="hljs-keyword">await</span> blocking_action()
|
||
</code></pre>
|
||
<p>
|
||
to avoid coroutines being confused with a regular generator (today <code>yield</code> is used in both).
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="24944096">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/24944096" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-15" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-15">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-15">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-15" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/24944096/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-24944096" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-4965zck0">Follow</button>
|
||
<div id="--stacks-s-tooltip-4965zck0" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/24944096/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2020-06-20 09:12:55Z" class="relativetime">Jun 20, 2020 at 9:12</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/-1/community">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/a007be5a61f6aa8f3e85ae2fc18dd66e?s=64&d=identicon&r=PG" alt="Community's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/-1/community">Community</a><span class="flex--item s-badge ml2 s-badge__xs mtn2" title="Community Bot — not a real person. Replies to this bot are not monitored.">Bot</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">1</span><span title="1 silver badge" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">1</span></span><span class="v-visible-sr">1 silver badge</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2014-07-24 21:15:29Z" class="relativetime">Jul 24, 2014 at 21:15</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1416144/s%c5%82awomir-lenart">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/bab2906fe97538ebda3121f8e9c04807?s=64&d=identicon&r=PG" alt="Sławomir Lenart's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1416144/s%c5%82awomir-lenart">Sławomir Lenart</a><span class="d-none" itemprop="name">Sławomir Lenart</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">6,732</span><span title="3 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 gold badges</span><span title="40 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">40</span></span><span class="v-visible-sr">40 silver badges</span><span title="58 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">58</span></span><span class="v-visible-sr">58 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-24944096" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="24944096" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-24944096" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="47285378" id="47285378"></a>
|
||
<div id="answer-47285378" class="answer js-answer" data-answerid="47285378" data-parentid="231767" data-score="146" data-position-on-page="16" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="47285378">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-j78zw4k8"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-j78zw4k8" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="146">
|
||
146
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-amfol8hr"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-amfol8hr" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-47285378" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="47285378" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-6zhmed0z"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-6zhmed0z" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/47285378/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-m4xb2hb1"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-m4xb2hb1" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
All great answers, however a bit difficult for newbies.
|
||
</p>
|
||
<p>
|
||
I assume you have learned the <code>return</code> statement.
|
||
</p>
|
||
<p>
|
||
As an analogy, <code>return</code> and <code>yield</code> are twins. <code>return</code> means 'return and stop' whereas 'yield` means 'return, but continue'
|
||
</p>
|
||
<blockquote>
|
||
<ol>
|
||
<li>Try to get a num_list with <code>return</code>.
|
||
</li>
|
||
</ol>
|
||
</blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">num_list</span>(<span class="hljs-params">n</span>):
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
|
||
<span class="hljs-keyword">return</span> i
|
||
</code></pre>
|
||
<p>
|
||
Run it:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">In [<span class="hljs-number">5</span>]: num_list(<span class="hljs-number">3</span>)
|
||
Out[<span class="hljs-number">5</span>]: <span class="hljs-number">0</span>
|
||
</code></pre>
|
||
<p>
|
||
See, you get only a single number rather than a list of them. <code>return</code> never allows you prevail happily, just implements once and quit.
|
||
</p>
|
||
<blockquote>
|
||
<ol start="2">
|
||
<li>There comes <code>yield</code>
|
||
</li>
|
||
</ol>
|
||
</blockquote>
|
||
<p>
|
||
Replace <code>return</code> with <code>yield</code>:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">In [<span class="hljs-number">10</span>]: <span class="hljs-keyword">def</span> <span class="hljs-title function_">num_list</span>(<span class="hljs-params">n</span>):
|
||
...: <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
|
||
...: <span class="hljs-keyword">yield</span> i
|
||
...:
|
||
|
||
In [<span class="hljs-number">11</span>]: num_list(<span class="hljs-number">3</span>)
|
||
Out[<span class="hljs-number">11</span>]: <generator <span class="hljs-built_in">object</span> num_list at <span class="hljs-number">0x10327c990</span>>
|
||
|
||
In [<span class="hljs-number">12</span>]: <span class="hljs-built_in">list</span>(num_list(<span class="hljs-number">3</span>))
|
||
Out[<span class="hljs-number">12</span>]: [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
|
||
</code></pre>
|
||
<p>
|
||
Now, you win to get all the numbers.
|
||
</p>
|
||
<p>
|
||
Comparing to <code>return</code> which runs once and stops, <code>yield</code> runs times you planed. You can interpret <code>return</code> as <code>return one of them</code>, and <code>yield</code> as <code>return all of them</code>. This is called <code>iterable</code>.
|
||
</p>
|
||
<blockquote>
|
||
<ol start="3">
|
||
<li>One more step we can rewrite <code>yield</code> statement with <code>return</code>
|
||
</li>
|
||
</ol>
|
||
</blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">In [<span class="hljs-number">15</span>]: <span class="hljs-keyword">def</span> <span class="hljs-title function_">num_list</span>(<span class="hljs-params">n</span>):
|
||
...: result = []
|
||
...: <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):
|
||
...: result.append(i)
|
||
...: <span class="hljs-keyword">return</span> result
|
||
|
||
In [<span class="hljs-number">16</span>]: num_list(<span class="hljs-number">3</span>)
|
||
Out[<span class="hljs-number">16</span>]: [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]
|
||
</code></pre>
|
||
<p>
|
||
It's the core about <code>yield</code>.
|
||
</p>
|
||
<p>
|
||
The difference between a list <code>return</code> outputs and the object <code>yield</code> output is:
|
||
</p>
|
||
<p>
|
||
You will always get [0, 1, 2] from a list object but only could retrieve them from 'the object <code>yield</code> output' once. So, it has a new name <code>generator</code> object as displayed in <code>Out[11]: <generator object num_list at 0x10327c990></code>.
|
||
</p>
|
||
<p>
|
||
In conclusion, as a metaphor to grok it:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<code>return</code> and <code>yield</code> are twins
|
||
</li>
|
||
<li>
|
||
<code>list</code> and <code>generator</code> are twins
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="47285378">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/47285378" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-16" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-16">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-16">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-16" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/47285378/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-47285378" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-tvyr29q3">Follow</button>
|
||
<div id="--stacks-s-tooltip-tvyr29q3" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/47285378/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-28 09:06:22Z" class="relativetime">May 28, 2018 at 9:06</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2017-11-14 12:02:47Z" class="relativetime">Nov 14, 2017 at 12:02</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/7301792/abstprocdo">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/K6k1M.png?s=64&g=1" alt="AbstProcDo's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/7301792/abstprocdo">AbstProcDo</a><span class="d-none" itemprop="name">AbstProcDo</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 18,889" dir="ltr">18.9k</span><span title="14 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">14</span></span><span class="v-visible-sr">14 gold badges</span><span title="74 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">74</span></span><span class="v-visible-sr">74 silver badges</span><span title="124 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">124</span></span><span class="v-visible-sr">124 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">1</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-47285378" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="47285378" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-90923314" class="comment js-comment" data-comment-id="90923314" data-comment-owner-id="3768749" data-comment-score="3">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="cool">3</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">This is understandable, but one major difference is that you can have multiple yields in a function/method. The analogy totally breaks down at that point. Yield remembers its place in a function, so the next time you call next(), your function continues on to the next <code>yield</code>. This is important, I think, and should be expressed.</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/3768749/mike-s" title="1,211 reputation" class="comment-user">Mike S</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment90923314_47285378" aria-label="Link to comment"><span title="2018-08-23 13:27:21Z, License: CC BY-SA 4.0" class="relativetime-clean">Aug 23, 2018 at 13:27</span></a></span> <span title="this comment was edited 1 time"><svg aria-hidden="true" class="va-text-bottom o50 svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-47285378" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="18365578" id="18365578"></a>
|
||
<div id="answer-18365578" class="answer js-answer" data-answerid="18365578" data-parentid="231767" data-score="133" data-position-on-page="17" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="18365578">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-1qdjfj21"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-1qdjfj21" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="133">
|
||
133
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-4o2g9jnn"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-4o2g9jnn" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-18365578" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="18365578" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-1b7l8k1x"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-1b7l8k1x" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/18365578/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-coahgo86"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-coahgo86" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
From a programming viewpoint, the iterators are implemented as <a href="http://en.wikipedia.org/wiki/Thunk_(functional_programming)" rel="noreferrer">thunks</a>.
|
||
</p>
|
||
<p>
|
||
To implement iterators, generators, and thread pools for concurrent execution, etc. as thunks, one uses <a href="https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent" rel="noreferrer">messages sent to a closure object</a>, which has a dispatcher, and the <a href="http://en.wikipedia.org/wiki/Message_passing" rel="noreferrer">dispatcher answers to "messages"</a>.
|
||
</p>
|
||
<p>
|
||
<a href="https://docs.python.org/3/library/functions.html#next" rel="noreferrer">"<em>next</em>"</a> is a message sent to a closure, created by the "<em>iter</em>" call.
|
||
</p>
|
||
<p>
|
||
There are lots of ways to implement this computation. I used mutation, but it is possible to do this kind of computation without mutation, by returning the current value and the next yielder (making it <a href="https://en.wikipedia.org/wiki/Referential_transparency" rel="noreferrer">referential transparent</a>). Racket uses a sequence of transformations of the initial program in some intermediary languages, one of such rewriting making the yield operator to be transformed in some language with simpler operators.
|
||
</p>
|
||
<p>
|
||
Here is a demonstration of how yield could be rewritten, which uses the structure of R6RS, but the semantics is identical to Python's. It's the same model of computation, and only a change in syntax is required to rewrite it using yield of Python.
|
||
</p>
|
||
<blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">Welcome to Racket v6<span class="hljs-number">.5</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span>.
|
||
|
||
-> (define gen
|
||
(<span class="hljs-keyword">lambda</span> (l)
|
||
(define <span class="hljs-keyword">yield</span>
|
||
(<span class="hljs-keyword">lambda</span> ()
|
||
(<span class="hljs-keyword">if</span> (null? l)
|
||
<span class="hljs-string">'END
|
||
(let ((v (car l)))
|
||
(set! l (cdr l))
|
||
v))))
|
||
(lambda(m)
|
||
(case m
|
||
('</span><span class="hljs-keyword">yield</span> (<span class="hljs-keyword">yield</span>))
|
||
(<span class="hljs-string">'init (lambda (data)
|
||
(set! l data)
|
||
'</span>OK))))))
|
||
-> (define stream (gen <span class="hljs-string">'(1 2 3)))
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-number">1</span>
|
||
-> (stream <span class="hljs-string">'yield)
|
||
2
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-number">3</span>
|
||
-> (stream <span class="hljs-string">'yield)
|
||
'</span>END
|
||
-> ((stream <span class="hljs-string">'init) '</span>(a b))
|
||
<span class="hljs-string">'OK
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-string">'a
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-string">'b
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-string">'END
|
||
-> (stream '</span><span class="hljs-keyword">yield</span>)
|
||
<span class="hljs-string">'END
|
||
->
|
||
</span></code></pre>
|
||
</blockquote>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="18365578">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/18365578" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-17" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-17">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-17">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-17" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/18365578/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-18365578" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-t7vla52e">Follow</button>
|
||
<div id="--stacks-s-tooltip-t7vla52e" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/18365578/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2020-07-02 07:36:31Z" class="relativetime">Jul 2, 2020 at 7:36</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-08-21 19:01:25Z" class="relativetime">Aug 21, 2013 at 19:01</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1419272/alinsoar">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/MmKoG.jpg?s=64&g=1" alt="alinsoar's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1419272/alinsoar">alinsoar</a><span class="d-none" itemprop="name">alinsoar</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 14,913" dir="ltr">14.9k</span><span title="4 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">4</span></span><span class="v-visible-sr">4 gold badges</span><span title="55 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">55</span></span><span class="v-visible-sr">55 silver badges</span><span title="71 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">71</span></span><span class="v-visible-sr">71 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-18365578" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="18365578" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-18365578" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="12716515" id="12716515"></a>
|
||
<div id="answer-12716515" class="answer js-answer" data-answerid="12716515" data-parentid="231767" data-score="127" data-position-on-page="18" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="12716515">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-sp6haram"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-sp6haram" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="127">
|
||
127
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-2sjnl05j"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-2sjnl05j" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-12716515" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="12716515" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-kiwty6wj"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-kiwty6wj" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/12716515/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-ovtb2rbo"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-ovtb2rbo" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Here are some Python examples of how to actually implement generators as if Python did not provide syntactic sugar for them:
|
||
</p>
|
||
<p>
|
||
<strong>As a Python generator:</strong>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">from</span> itertools <span class="hljs-keyword">import</span> islice
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">fib_gen</span>():
|
||
a, b = <span class="hljs-number">1</span>, <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-keyword">yield</span> a
|
||
a, b = b, a + b
|
||
|
||
<span class="hljs-keyword">assert</span> [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>] == <span class="hljs-built_in">list</span>(islice(fib_gen(), <span class="hljs-number">5</span>))
|
||
</code></pre>
|
||
<p>
|
||
<strong>Using lexical closures instead of generators</strong>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">ftake</span>(<span class="hljs-params">fnext, last</span>):
|
||
<span class="hljs-keyword">return</span> [fnext() <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> xrange(last)]
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">fib_gen2</span>():
|
||
<span class="hljs-comment">#funky scope due to python2.x workaround</span>
|
||
<span class="hljs-comment">#for python 3.x use nonlocal</span>
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_</span>():
|
||
_.a, _.b = _.b, _.a + _.b
|
||
<span class="hljs-keyword">return</span> _.a
|
||
_.a, _.b = <span class="hljs-number">0</span>, <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">return</span> _
|
||
|
||
<span class="hljs-keyword">assert</span> [<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">5</span>] == ftake(fib_gen2(), <span class="hljs-number">5</span>)
|
||
</code></pre>
|
||
<p>
|
||
<strong>Using object closures instead of generators</strong> (because <a href="http://c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent" rel="noreferrer">ClosuresAndObjectsAreEquivalent</a>)
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">fib_gen3</span>:
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
|
||
self.a, self.b = <span class="hljs-number">1</span>, <span class="hljs-number">1</span>
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__call__</span>(<span class="hljs-params">self</span>):
|
||
r = self.a
|
||
self.a, self.b = self.b, self.a + self.b
|
||
<span class="hljs-keyword">return</span> r
|
||
|
||
<span class="hljs-keyword">assert</span> [<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">5</span>] == ftake(fib_gen3(), <span class="hljs-number">5</span>)
|
||
</code></pre>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="12716515">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/12716515" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-18" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-18">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-18">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-18" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/12716515/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-12716515" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-ty26f99l">Follow</button>
|
||
<div id="--stacks-s-tooltip-ty26f99l" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/12716515/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2017-10-24 10:46:05Z" class="relativetime">Oct 24, 2017 at 10:46</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2012-10-03 20:38:16Z" class="relativetime">Oct 3, 2012 at 20:38</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/20003/dustin-getz">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/8c8dd2e41a62328fe8502000bc5a45ca?s=64&d=identicon&r=PG" alt="Dustin Getz's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/20003/dustin-getz">Dustin Getz</a><span class="d-none" itemprop="name">Dustin Getz</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 20,876" dir="ltr">20.9k</span><span title="14 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">14</span></span><span class="v-visible-sr">14 gold badges</span><span title="81 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">81</span></span><span class="v-visible-sr">81 silver badges</span><span title="129 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">129</span></span><span class="v-visible-sr">129 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-12716515" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="12716515" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-12716515" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="14554322" id="14554322"></a>
|
||
<div id="answer-14554322" class="answer js-answer" data-answerid="14554322" data-parentid="231767" data-score="116" data-position-on-page="19" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="14554322">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-vpgw0spg"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-vpgw0spg" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="116">
|
||
116
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-1jvnj1ry"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-1jvnj1ry" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-14554322" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="14554322" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-4w2oxhpn"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-4w2oxhpn" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/14554322/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-phwqgfk6"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-phwqgfk6" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
I was going to post "read page 19 of Beazley's 'Python: Essential Reference' for a quick description of generators", but so many others have posted good descriptions already.
|
||
</p>
|
||
<p>
|
||
Also, note that <code>yield</code> can be used in coroutines as the dual of their use in generator functions. Although it isn't the same use as your code snippet, <code>(yield)</code> can be used as an expression in a function. When a caller sends a value to the method using the <code>send()</code> method, then the coroutine will execute until the next <code>(yield)</code> statement is encountered.
|
||
</p>
|
||
<p>
|
||
Generators and coroutines are a cool way to set up data-flow type applications. I thought it would be worthwhile knowing about the other use of the <code>yield</code> statement in functions.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="14554322">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/14554322" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-19" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-19">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-19">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-19" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/14554322/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-14554322" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-w3exlcje">Follow</button>
|
||
<div id="--stacks-s-tooltip-w3exlcje" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-01-28 01:37:10Z" class="relativetime">Jan 28, 2013 at 1:37</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/479213/johnzachary">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/fb5e966ed938c254a8846613fa110030?s=64&d=identicon&r=PG" alt="johnzachary's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/479213/johnzachary">johnzachary</a><span class="d-none" itemprop="name">johnzachary</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,395</span><span title="2 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">2</span></span><span class="v-visible-sr">2 gold badges</span><span title="18 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">18</span></span><span class="v-visible-sr">18 silver badges</span><span title="9 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">9</span></span><span class="v-visible-sr">9 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-14554322" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="14554322" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-14554322" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="20704301" id="20704301"></a>
|
||
<div id="answer-20704301" class="answer js-answer" data-answerid="20704301" data-parentid="231767" data-score="100" data-position-on-page="20" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="20704301">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-323pztk5"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-323pztk5" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="100">
|
||
100
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-l1x2js43"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-l1x2js43" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-20704301" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="20704301" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-t5yem1cd"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-t5yem1cd" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/20704301/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-tilkqnj4"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-tilkqnj4" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Here is a simple example:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">isPrimeNumber</span>(<span class="hljs-params">n</span>):
|
||
<span class="hljs-built_in">print</span> <span class="hljs-string">"isPrimeNumber({}) call"</span>.<span class="hljs-built_in">format</span>(n)
|
||
<span class="hljs-keyword">if</span> n==<span class="hljs-number">1</span>:
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
|
||
<span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">2</span>,n):
|
||
<span class="hljs-keyword">if</span> n % x == <span class="hljs-number">0</span>:
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
|
||
<span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">primes</span> (n=<span class="hljs-number">1</span>):
|
||
<span class="hljs-keyword">while</span>(<span class="hljs-literal">True</span>):
|
||
<span class="hljs-built_in">print</span> <span class="hljs-string">"loop step ---------------- {}"</span>.<span class="hljs-built_in">format</span>(n)
|
||
<span class="hljs-keyword">if</span> isPrimeNumber(n): <span class="hljs-keyword">yield</span> n
|
||
n += <span class="hljs-number">1</span>
|
||
|
||
<span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> primes():
|
||
<span class="hljs-keyword">if</span> n> <span class="hljs-number">10</span>:<span class="hljs-keyword">break</span>
|
||
<span class="hljs-built_in">print</span> <span class="hljs-string">"wiriting result {}"</span>.<span class="hljs-built_in">format</span>(n)
|
||
</code></pre>
|
||
<p>
|
||
Output:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">loop step ---------------- <span class="hljs-number">1</span>
|
||
isPrimeNumber(<span class="hljs-number">1</span>) call
|
||
loop step ---------------- <span class="hljs-number">2</span>
|
||
isPrimeNumber(<span class="hljs-number">2</span>) call
|
||
loop step ---------------- <span class="hljs-number">3</span>
|
||
isPrimeNumber(<span class="hljs-number">3</span>) call
|
||
wiriting result <span class="hljs-number">3</span>
|
||
loop step ---------------- <span class="hljs-number">4</span>
|
||
isPrimeNumber(<span class="hljs-number">4</span>) call
|
||
loop step ---------------- <span class="hljs-number">5</span>
|
||
isPrimeNumber(<span class="hljs-number">5</span>) call
|
||
wiriting result <span class="hljs-number">5</span>
|
||
loop step ---------------- <span class="hljs-number">6</span>
|
||
isPrimeNumber(<span class="hljs-number">6</span>) call
|
||
loop step ---------------- <span class="hljs-number">7</span>
|
||
isPrimeNumber(<span class="hljs-number">7</span>) call
|
||
wiriting result <span class="hljs-number">7</span>
|
||
loop step ---------------- <span class="hljs-number">8</span>
|
||
isPrimeNumber(<span class="hljs-number">8</span>) call
|
||
loop step ---------------- <span class="hljs-number">9</span>
|
||
isPrimeNumber(<span class="hljs-number">9</span>) call
|
||
loop step ---------------- <span class="hljs-number">10</span>
|
||
isPrimeNumber(<span class="hljs-number">10</span>) call
|
||
loop step ---------------- <span class="hljs-number">11</span>
|
||
isPrimeNumber(<span class="hljs-number">11</span>) call
|
||
</code></pre>
|
||
<p>
|
||
I am not a Python developer, but it looks to me <code>yield</code> holds the position of program flow and the next loop start from "yield" position. It seems like it is waiting at that position, and just before that, returning a value outside, and next time continues to work.
|
||
</p>
|
||
<p>
|
||
It seems to be an interesting and nice ability :D
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="20704301">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/20704301" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-20" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-20">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-20">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-20" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/20704301/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-20704301" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-1sih4531">Follow</button>
|
||
<div id="--stacks-s-tooltip-1sih4531" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/20704301/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 10:31:01Z" class="relativetime">May 20, 2018 at 10:31</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-12-20 13:07:18Z" class="relativetime">Dec 20, 2013 at 13:07</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1077381/engin-ozturk">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/p3GZL.png?s=64&g=1" alt="Engin OZTURK's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1077381/engin-ozturk">Engin OZTURK</a><span class="d-none" itemprop="name">Engin OZTURK</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,035</span><span title="2 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">2</span></span><span class="v-visible-sr">2 gold badges</span><span title="21 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 silver badges</span><span title="13 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">13</span></span><span class="v-visible-sr">13 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">1</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-20704301" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="20704301" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-89241413" class="comment js-comment" data-comment-id="89241413" data-comment-owner-id="1077381" data-comment-score="0">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide"></div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">You are correct. But what is the effect on flow which is to see the behaviour of "yield" ? I can change the algorithm in the name of mathmatics. Will it help to get different assessment of "yield" ?</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/1077381/engin-ozturk" title="2,035 reputation" class="comment-user">Engin OZTURK</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment89241413_20704301" aria-label="Link to comment"><span title="2018-07-02 01:44:08Z, License: CC BY-SA 4.0" class="relativetime-clean">Jul 2, 2018 at 1:44</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-20704301" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="17113322" id="17113322"></a>
|
||
<div id="answer-17113322" class="answer js-answer" data-answerid="17113322" data-parentid="231767" data-score="86" data-position-on-page="21" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="17113322">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-4y2uav6i"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-4y2uav6i" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="86">
|
||
86
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-hvttyrlk"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-hvttyrlk" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-17113322" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="17113322" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-tnygrwtg"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-tnygrwtg" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/17113322/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-5tday0ni"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-5tday0ni" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Here is a mental image of what <code>yield</code> does.
|
||
</p>
|
||
<p>
|
||
I like to think of a thread as having a stack (even when it's not implemented that way).
|
||
</p>
|
||
<p>
|
||
When a normal function is called, it puts its local variables on the stack, does some computation, then clears the stack and returns. The values of its local variables are never seen again.
|
||
</p>
|
||
<p>
|
||
With a <code>yield</code> function, when its code begins to run (i.e. after the function is called, returning a generator object, whose <code>next()</code> method is then invoked), it similarly puts its local variables onto the stack and computes for a while. But then, when it hits the <code>yield</code> statement, before clearing its part of the stack and returning, it takes a snapshot of its local variables and stores them in the generator object. It also writes down the place where it's currently up to in its code (i.e. the particular <code>yield</code> statement).
|
||
</p>
|
||
<p>
|
||
So it's a kind of a frozen function that the generator is hanging onto.
|
||
</p>
|
||
<p>
|
||
When <code>next()</code> is called subsequently, it retrieves the function's belongings onto the stack and re-animates it. The function continues to compute from where it left off, oblivious to the fact that it had just spent an eternity in cold storage.
|
||
</p>
|
||
<p>
|
||
Compare the following examples:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">normalFunction</span>():
|
||
<span class="hljs-keyword">return</span>
|
||
<span class="hljs-keyword">if</span> <span class="hljs-literal">False</span>:
|
||
<span class="hljs-keyword">pass</span>
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">yielderFunction</span>():
|
||
<span class="hljs-keyword">return</span>
|
||
<span class="hljs-keyword">if</span> <span class="hljs-literal">False</span>:
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">12</span>
|
||
</code></pre>
|
||
<p>
|
||
When we call the second function, it behaves very differently to the first. The <code>yield</code> statement might be unreachable, but if it's present anywhere, it changes the nature of what we're dealing with.
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>yielderFunction()
|
||
<generator <span class="hljs-built_in">object</span> yielderFunction at <span class="hljs-number">0x07742D28</span>>
|
||
</code></pre>
|
||
<p>
|
||
Calling <code>yielderFunction()</code> doesn't run its code, but makes a generator out of the code. (Maybe it's a good idea to name such things with the <code>yielder</code> prefix for readability.)
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-meta">>>> </span>gen = yielderFunction()
|
||
<span class="hljs-meta">>>> </span><span class="hljs-built_in">dir</span>(gen)
|
||
[<span class="hljs-string">'__class__'</span>,
|
||
...
|
||
<span class="hljs-string">'__iter__'</span>, <span class="hljs-comment">#Returns gen itself, to make it work uniformly with containers</span>
|
||
... <span class="hljs-comment">#when given to a for loop. (Containers return an iterator instead.)</span>
|
||
<span class="hljs-string">'close'</span>,
|
||
<span class="hljs-string">'gi_code'</span>,
|
||
<span class="hljs-string">'gi_frame'</span>,
|
||
<span class="hljs-string">'gi_running'</span>,
|
||
<span class="hljs-string">'next'</span>, <span class="hljs-comment">#The method that runs the function's body.</span>
|
||
<span class="hljs-string">'send'</span>,
|
||
<span class="hljs-string">'throw'</span>]
|
||
</code></pre>
|
||
<p>
|
||
The <code>gi_code</code> and <code>gi_frame</code> fields are where the frozen state is stored. Exploring them with <code>dir(..)</code>, we can confirm that our mental model above is credible.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="17113322">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/17113322" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-21" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-21">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-21">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-21" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/17113322/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-17113322" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-7l6325xv">Follow</button>
|
||
<div id="--stacks-s-tooltip-7l6325xv" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/17113322/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2017-03-01 13:36:58Z" class="relativetime">Mar 1, 2017 at 13:36</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2013-06-14 16:36:59Z" class="relativetime">Jun 14, 2013 at 16:36</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/1143274/evgeni-sergeev">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/bf11af111cab6e513d68e5e30762deb5?s=64&d=identicon&r=PG" alt="Evgeni Sergeev's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/1143274/evgeni-sergeev">Evgeni Sergeev</a><span class="d-none" itemprop="name">Evgeni Sergeev</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 21,806" dir="ltr">21.8k</span><span title="16 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">16</span></span><span class="v-visible-sr">16 gold badges</span><span title="103 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">103</span></span><span class="v-visible-sr">103 silver badges</span><span title="123 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">123</span></span><span class="v-visible-sr">123 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-17113322" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="17113322" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-17113322" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="55314423" id="55314423"></a>
|
||
<div id="answer-55314423" class="answer js-answer" data-answerid="55314423" data-parentid="231767" data-score="82" data-position-on-page="22" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="55314423">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-s7dacy4u"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-s7dacy4u" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="82">
|
||
82
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-yoz3gytn"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-yoz3gytn" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-55314423" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="55314423" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-1kejw09b"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-1kejw09b" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/55314423/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-na5cm4d5"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-na5cm4d5" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<img src="https://i.stack.imgur.com/AJZlN.png" width="300" />
|
||
<p>
|
||
Imagine that you have created a remarkable machine that is capable of generating thousands and thousands of lightbulbs per day. The machine generates these lightbulbs in boxes with a unique serial number. You don't have enough space to store all of these lightbulbs at the same time, so you would like to adjust it to generate lightbulbs on-demand.
|
||
</p>
|
||
<p>
|
||
Python generators don't differ much from this concept. Imagine that you have a function called <code>barcode_generator</code> that generates unique serial numbers for the boxes. Obviously, you can have a huge number of such barcodes returned by the function, subject to the hardware (RAM) limitations. A wiser, and space efficient, option is to generate those serial numbers on-demand.
|
||
</p>
|
||
<p>
|
||
Machine's code:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">barcode_generator</span>():
|
||
serial_number = <span class="hljs-number">10000</span> <span class="hljs-comment"># Initial barcode</span>
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
<span class="hljs-keyword">yield</span> serial_number
|
||
serial_number += <span class="hljs-number">1</span>
|
||
|
||
|
||
barcode = barcode_generator()
|
||
<span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
|
||
number_of_lightbulbs_to_generate = <span class="hljs-built_in">int</span>(<span class="hljs-built_in">input</span>(<span class="hljs-string">"How many lightbulbs to generate? "</span>))
|
||
barcodes = [<span class="hljs-built_in">next</span>(barcode) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(number_of_lightbulbs_to_generate)]
|
||
<span class="hljs-built_in">print</span>(barcodes)
|
||
|
||
<span class="hljs-comment"># function_to_create_the_next_batch_of_lightbulbs(barcodes)</span>
|
||
|
||
produce_more = <span class="hljs-built_in">input</span>(<span class="hljs-string">"Produce more? [Y/n]: "</span>)
|
||
<span class="hljs-keyword">if</span> produce_more == <span class="hljs-string">"n"</span>:
|
||
<span class="hljs-keyword">break</span>
|
||
</code></pre>
|
||
<p>
|
||
Note the <code>next(barcode)</code> bit.
|
||
</p>
|
||
<p>
|
||
As you can see, we have a self-contained “function” to generate the next unique serial number each time. This function returns a <em>generator</em>! As you can see, we are not calling the function each time we need a new serial number, but instead we are using <code>next()</code> given the generator to obtain the next serial number.
|
||
</p>
|
||
<h1>
|
||
Lazy Iterators
|
||
</h1>
|
||
<p>
|
||
To be more precise, this generator is a <em>lazy iterator</em>! An iterator is an object that helps us traverse a sequence of objects. It's called <em>lazy</em> because it does not load all the items of the sequence in memory until they are needed. The use of <code>next</code> in the previous example is the <em>explicit</em> way to obtain the next item from the iterator. The <em>implicit</em> way is using for loops:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> barcode <span class="hljs-keyword">in</span> barcode_generator():
|
||
<span class="hljs-built_in">print</span>(barcode)
|
||
</code></pre>
|
||
<p>
|
||
This will print barcodes infinitely, yet you will not run out of memory.
|
||
</p>
|
||
<p>
|
||
<strong>In other words, a generator <em>looks like</em> a function but <em>behaves like</em> an iterator.</strong>
|
||
</p>
|
||
<h1>
|
||
Real-world application?
|
||
</h1>
|
||
<p>
|
||
Finally, real-world applications? They are usually useful when you work with big sequences. Imagine reading a <em>huge</em> file from disk with billions of records. Reading the entire file in memory, before you can work with its content, will probably be infeasible (i.e., you will run out of memory).
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="55314423">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/55314423" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-22" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-22">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-22">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-22" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/55314423/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-55314423" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-ga1n7niy">Follow</button>
|
||
<div id="--stacks-s-tooltip-ga1n7niy" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/55314423/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2021-10-21 18:54:29Z" class="relativetime">Oct 21, 2021 at 18:54</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2019-03-23 13:55:51Z" class="relativetime">Mar 23, 2019 at 13:55</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/4946896/dr-rafael">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/dbe7e09627974c401e4eca85d23cefe5?s=64&d=identicon&r=PG&f=1" alt="Dr Rafael's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/4946896/dr-rafael">Dr Rafael</a><span class="d-none" itemprop="name">Dr Rafael</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">6,717</span><span title="5 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">5</span></span><span class="v-visible-sr">5 gold badges</span><span title="42 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">42</span></span><span class="v-visible-sr">42 silver badges</span><span title="50 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">50</span></span><span class="v-visible-sr">50 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-55314423" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="55314423" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-55314423" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="41426583" id="41426583"></a>
|
||
<div id="answer-41426583" class="answer js-answer" data-answerid="41426583" data-parentid="231767" data-score="78" data-position-on-page="23" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="41426583">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-cnohsgll"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-cnohsgll" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="78">
|
||
78
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-sxjmu258"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-sxjmu258" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-41426583" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="41426583" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-wy3juotd"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-wy3juotd" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/41426583/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-ewk65zoc"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-ewk65zoc" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
An easy example to understand what it is: <code>yield</code>
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">f123</span>():
|
||
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">4</span>):
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-number">2</span>
|
||
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> f123():
|
||
<span class="hljs-built_in">print</span> (i)
|
||
</code></pre>
|
||
<p>
|
||
The output is:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span>
|
||
</code></pre>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="41426583">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/41426583" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-23" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-23">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-23">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-23" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/41426583/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-41426583" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-z5p4egf5">Follow</button>
|
||
<div id="--stacks-s-tooltip-z5p4egf5" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/41426583/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2020-02-02 18:21:38Z" class="relativetime">Feb 2, 2020 at 18:21</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/8928024/zf007">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/75f4b1f5d87975964979ce2718af1ae9?s=64&d=identicon&r=PG&f=1" alt="ZF007's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/8928024/zf007">ZF007</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">3,646</span><span title="8 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">8</span></span><span class="v-visible-sr">8 gold badges</span><span title="33 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">33</span></span><span class="v-visible-sr">33 silver badges</span><span title="48 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">48</span></span><span class="v-visible-sr">48 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2017-01-02 12:09:28Z" class="relativetime">Jan 2, 2017 at 12:09</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/5770004/gavriel-cohen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/g5w2q.png?s=64&g=1" alt="Gavriel Cohen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/5770004/gavriel-cohen">Gavriel Cohen</a><span class="d-none" itemprop="name">Gavriel Cohen</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">4,100</span><span title="32 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">32</span></span><span class="v-visible-sr">32 silver badges</span><span title="38 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">38</span></span><span class="v-visible-sr">38 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">2</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-41426583" class="comments js-comments-container bt bc-black-075 mt12" data-post-id="41426583" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true">
|
||
<li id="comment-106237799" class="comment js-comment" data-comment-id="106237799" data-comment-owner-id="9074332" data-comment-score="8">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="warm">8</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">are you sure about that output? wouldnt that only be printed on a single line if you ran that print statement using <code>print(i, end=' ')</code>? Otherwise, i believe the default behavior would put each number on a new line</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/9074332/user9074332" title="2,156 reputation" class="comment-user">user9074332</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment106237799_41426583" aria-label="Link to comment"><span title="2020-02-05 04:05:56Z, License: CC BY-SA 4.0" class="relativetime-clean">Feb 5, 2020 at 4:05</span></a></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
<li id="comment-106255539" class="comment js-comment" data-comment-id="106255539" data-comment-owner-id="5770004" data-comment-score="3">
|
||
<div class="js-comment-actions comment-actions">
|
||
<div class="comment-score js-comment-edit-hide">
|
||
<span title="number of 'useful comment' votes received" class="cool">3</span>
|
||
</div>
|
||
</div>
|
||
<div class="comment-text js-comment-text-and-form">
|
||
<div class="comment-body js-comment-edit-hide">
|
||
<span class="comment-copy">@user9074332, You're right, but it is written on one line to facilitate understanding</span>
|
||
<div class="d-inline-flex ai-center">
|
||
– <a href="/users/5770004/gavriel-cohen" title="4,100 reputation" class="comment-user">Gavriel Cohen</a>
|
||
</div><span class="comment-date" dir="ltr"><a class="comment-link" href="#comment106255539_41426583" aria-label="Link to comment"><span title="2020-02-05 14:58:14Z, License: CC BY-SA 4.0" class="relativetime-clean">Feb 5, 2020 at 14:58</span></a></span> <span title="this comment was edited 1 time"><svg aria-hidden="true" class="va-text-bottom o50 svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg></span>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="comments-link-41426583" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="31692481" id="31692481"></a>
|
||
<div id="answer-31692481" class="answer js-answer" data-answerid="31692481" data-parentid="231767" data-score="74" data-position-on-page="24" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="31692481">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-zhljzmij"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-zhljzmij" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="74">
|
||
74
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-sydpfpxx"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-sydpfpxx" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-31692481" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="31692481" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-ukwvf1jm"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-ukwvf1jm" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/31692481/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-osgsvf2v"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-osgsvf2v" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Like every answer suggests, <code>yield</code> is used for creating a sequence generator. It's used for generating some sequence dynamically. For example, while reading a file line by line on a network, you can use the <code>yield</code> function as follows:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">getNextLines</span>():
|
||
<span class="hljs-keyword">while</span> con.isOpen():
|
||
<span class="hljs-keyword">yield</span> con.read()
|
||
</code></pre>
|
||
<p>
|
||
You can use it in your code as follows:
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> getNextLines():
|
||
doSomeThing(line)
|
||
</code></pre>
|
||
<p>
|
||
<strong><em>Execution Control Transfer gotcha</em></strong>
|
||
</p>
|
||
<p>
|
||
The execution control will be transferred from getNextLines() to the <code>for</code> loop when yield is executed. Thus, every time getNextLines() is invoked, execution begins from the point where it was paused last time.
|
||
</p>
|
||
<p>
|
||
Thus in short, a function with the following code
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">simpleYield</span>():
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">"first time"</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">"second time"</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">"third time"</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">"Now some useful value {}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-number">12</span>)
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> simpleYield():
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
will print
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-string">"first time"</span>
|
||
<span class="hljs-string">"second time"</span>
|
||
<span class="hljs-string">"third time"</span>
|
||
<span class="hljs-string">"Now some useful value 12"</span>
|
||
</code></pre>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="31692481">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/31692481" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-24" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-24">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-24">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-24" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/31692481/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-31692481" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-00vpdaqy">Follow</button>
|
||
<div id="--stacks-s-tooltip-00vpdaqy" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/31692481/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 10:42:59Z" class="relativetime">May 20, 2018 at 10:42</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2015-07-29 06:11:25Z" class="relativetime">Jul 29, 2015 at 6:11</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2393267/mangu-singh-rajpurohit">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/PVkBB.jpg?s=64&g=1" alt="Mangu Singh Rajpurohit's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/2393267/mangu-singh-rajpurohit">Mangu Singh Rajpurohit</a><span class="d-none" itemprop="name">Mangu Singh Rajpurohit</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 10,190" dir="ltr">10.2k</span><span title="4 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">4</span></span><span class="v-visible-sr">4 gold badges</span><span title="61 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">61</span></span><span class="v-visible-sr">61 silver badges</span><span title="94 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">94</span></span><span class="v-visible-sr">94 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-31692481" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="31692481" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-31692481" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="36214653" id="36214653"></a>
|
||
<div id="answer-36214653" class="answer js-answer" data-answerid="36214653" data-parentid="231767" data-score="72" data-position-on-page="25" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="36214653">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-703msyhl"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-703msyhl" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="72">
|
||
72
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-ke8zzpun"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-ke8zzpun" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-36214653" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="36214653" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-awg000zc"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-awg000zc" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/36214653/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-w52e5s94"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-w52e5s94" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
(My below answer only speaks from the perspective of using Python generator, not the <a href="https://stackoverflow.com/questions/8389812/how-are-generators-and-coroutines-implemented-in-cpython">underlying implementation of generator mechanism</a>, which involves some tricks of stack and heap manipulation.)
|
||
</p>
|
||
<p>
|
||
When <code>yield</code> is used instead of a <code>return</code> in a python function, that function is turned into something special called <code>generator function</code>. That function will return an object of <code>generator</code> type. <strong>The <code>yield</code> keyword is a flag to notify the python compiler to treat such function specially.</strong> Normal functions will terminate once some value is returned from it. But with the help of the compiler, the generator function <strong>can be thought of</strong> as resumable. That is, the execution context will be restored and the execution will continue from last run. Until you explicitly call return, which will raise a <code>StopIteration</code> exception (which is also part of the iterator protocol), or reach the end of the function. I found a lot of references about <code>generator</code> but this <a href="https://docs.python.org/dev/howto/functional.html#generators" rel="noreferrer">one</a> from the <code>functional programming perspective</code> is the most digestable.
|
||
</p>
|
||
<p>
|
||
(Now I want to talk about the rationale behind <code>generator</code>, and the <code>iterator</code> based on my own understanding. I hope this can help you grasp the <strong><em>essential motivation</em></strong> of iterator and generator. Such concept shows up in other languages as well such as C#.)
|
||
</p>
|
||
<p>
|
||
As I understand, when we want to process a bunch of data, we usually first store the data somewhere and then process it one by one. But this <em>naive</em> approach is problematic. If the data volume is huge, it's expensive to store them as a whole beforehand. <strong>So instead of storing the <code>data</code> itself directly, why not store some kind of <code>metadata</code> indirectly, i.e. <code>the logic how the data is computed</code></strong>.
|
||
</p>
|
||
<p>
|
||
There are 2 approaches to wrap such metadata.
|
||
</p>
|
||
<ol>
|
||
<li>The OO approach, we wrap the metadata <code>as a class</code>. This is the so-called <code>iterator</code> who implements the iterator protocol (i.e. the <code>__next__()</code>, and <code>__iter__()</code> methods). This is also the commonly seen <a href="https://en.wikipedia.org/wiki/Iterator_pattern#Python" rel="noreferrer">iterator design pattern</a>.
|
||
</li>
|
||
<li>The functional approach, we wrap the metadata <code>as a function</code>. This is the so-called <code>generator function</code>. But under the hood, the returned <code>generator object</code> still <code>IS-A</code> iterator because it also implements the iterator protocol.
|
||
</li>
|
||
</ol>
|
||
<p>
|
||
Either way, an iterator is created, i.e. some object that can give you the data you want. The OO approach may be a bit complex. Anyway, which one to use is up to you.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="36214653">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/36214653" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-25" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-25">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-25">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-25" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/36214653/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-36214653" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-3xwcrbh1">Follow</button>
|
||
<div id="--stacks-s-tooltip-3xwcrbh1" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/36214653/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-11-23 01:38:59Z" class="relativetime">Nov 23, 2018 at 1:38</span></a>
|
||
</div>
|
||
<div class="user-gravatar32"></div>
|
||
<div class="user-details">
|
||
<div class="-flair"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2016-03-25 05:40:24Z" class="relativetime">Mar 25, 2016 at 5:40</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/264052/smwikipedia">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/8ccbe08a132ba61eae9ff8984ca44e81?s=64&d=identicon&r=PG" alt="smwikipedia's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/264052/smwikipedia">smwikipedia</a><span class="d-none" itemprop="name">smwikipedia</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 59,431" dir="ltr">59.4k</span><span title="90 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">90</span></span><span class="v-visible-sr">90 gold badges</span><span title="293 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">293</span></span><span class="v-visible-sr">293 silver badges</span><span title="468 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">468</span></span><span class="v-visible-sr">468 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><span class="d-none" itemprop="commentCount">0</span>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-36214653" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="36214653" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-36214653" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="40022748" id="40022748"></a>
|
||
<div id="answer-40022748" class="answer js-answer" data-answerid="40022748" data-parentid="231767" data-score="71" data-position-on-page="26" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="40022748">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-fl0fyqrf"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-fl0fyqrf" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="71">
|
||
71
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-hncb3xyo"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-hncb3xyo" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-40022748" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="40022748" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-8cprzw66"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-8cprzw66" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/40022748/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-y3f9auet"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-y3f9auet" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
In summary, the <code>yield</code> statement transforms your function into a factory that produces a special object called a <code>generator</code> which wraps around the body of your original function. When the <code>generator</code> is iterated, it executes your function until it reaches the next <code>yield</code> then suspends execution and evaluates to the value passed to <code>yield</code>. It repeats this process on each iteration until the path of execution exits the function. For instance,
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">simple_generator</span>():
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'one'</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'two'</span>
|
||
<span class="hljs-keyword">yield</span> <span class="hljs-string">'three'</span>
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> simple_generator():
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
simply outputs
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">one
|
||
two
|
||
three
|
||
</code></pre>
|
||
<p>
|
||
The power comes from using the generator with a loop that calculates a sequence, the generator executes the loop stopping each time to 'yield' the next result of the calculation, in this way it calculates a list on the fly, the benefit being the memory saved for especially large calculations
|
||
</p>
|
||
<p>
|
||
Say you wanted to create a your own <code>range</code> function that produces an iterable range of numbers, you could do it like so,
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">myRangeNaive</span>(<span class="hljs-params">i</span>):
|
||
n = <span class="hljs-number">0</span>
|
||
<span class="hljs-built_in">range</span> = []
|
||
<span class="hljs-keyword">while</span> n < i:
|
||
<span class="hljs-built_in">range</span>.append(n)
|
||
n = n + <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">return</span> <span class="hljs-built_in">range</span>
|
||
</code></pre>
|
||
<p>
|
||
and use it like this;
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> myRangeNaive(<span class="hljs-number">10</span>):
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
But this is inefficient because
|
||
</p>
|
||
<ul>
|
||
<li>You create an array that you only use once (this wastes memory)
|
||
</li>
|
||
<li>This code actually loops over that array twice! :(
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
Luckily Guido and his team were generous enough to develop generators so we could just do this;
|
||
</p>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">myRangeSmart</span>(<span class="hljs-params">i</span>):
|
||
n = <span class="hljs-number">0</span>
|
||
<span class="hljs-keyword">while</span> n < i:
|
||
<span class="hljs-keyword">yield</span> n
|
||
n = n + <span class="hljs-number">1</span>
|
||
<span class="hljs-keyword">return</span>
|
||
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> myRangeSmart(<span class="hljs-number">10</span>):
|
||
<span class="hljs-built_in">print</span> i
|
||
</code></pre>
|
||
<p>
|
||
Now upon each iteration a function on the generator called <code>next()</code> executes the function until it either reaches a 'yield' statement in which it stops and 'yields' the value or reaches the end of the function. In this case on the first call, <code>next()</code> executes up to the yield statement and yield 'n', on the next call it will execute the increment statement, jump back to the 'while', evaluate it, and if true, it will stop and yield 'n' again, it will continue that way until the while condition returns false and the generator jumps to the end of the function.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="40022748">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/40022748" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-26" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-26">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-26">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-26" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/40022748/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-40022748" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-5qc4zgzp">Follow</button>
|
||
<div id="--stacks-s-tooltip-5qc4zgzp" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/40022748/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 11:04:36Z" class="relativetime">May 20, 2018 at 11:04</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2016-10-13 13:43:40Z" class="relativetime">Oct 13, 2016 at 13:43</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/3104473/redbandit">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/?s=64&d=identicon&r=PG&f=1" alt="redbandit's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/3104473/redbandit">redbandit</a><span class="d-none" itemprop="name">redbandit</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,072</span><span title="15 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">15</span></span><span class="v-visible-sr">15 silver badges</span><span title="11 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">11</span></span><span class="v-visible-sr">11 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-40022748" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="40022748" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-40022748" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="32331953" id="32331953"></a>
|
||
<div id="answer-32331953" class="answer js-answer" data-answerid="32331953" data-parentid="231767" data-score="67" data-position-on-page="27" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="32331953">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-re1zypxr"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-re1zypxr" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="67">
|
||
67
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-dc7m2vrl"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-dc7m2vrl" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-32331953" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="32331953" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-lqqurm4r"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-lqqurm4r" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/32331953/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-1fgdz3ea"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-1fgdz3ea" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
<strong>Yield is an object</strong>
|
||
</p>
|
||
<p>
|
||
A <code>return</code> in a function will return a single value.
|
||
</p>
|
||
<p>
|
||
If you want <strong>a function to return a huge set of values</strong>, use <code>yield</code>.
|
||
</p>
|
||
<p>
|
||
More importantly, <code>yield</code> is a <strong>barrier</strong>.
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
like barrier in the CUDA language, it will not transfer control until it gets completed.
|
||
</p>
|
||
</blockquote>
|
||
<p>
|
||
That is, it will run the code in your function from the beginning until it hits <code>yield</code>. Then, it’ll return the first value of the loop.
|
||
</p>
|
||
<p>
|
||
Then, every other call will run the loop you have written in the function one more time, returning the next value until there isn't any value to return.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="32331953">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/32331953" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-27" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-27">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-27">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-27" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/32331953/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-32331953" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-80obp4nc">Follow</button>
|
||
<div id="--stacks-s-tooltip-80obp4nc" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/32331953/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 10:45:50Z" class="relativetime">May 20, 2018 at 10:45</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2015-09-01 12:42:19Z" class="relativetime">Sep 1, 2015 at 12:42</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/2046817/kaleem-ullah">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/GWBHx.jpg?s=64&g=1" alt="Kaleem Ullah's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/2046817/kaleem-ullah">Kaleem Ullah</a><span class="d-none" itemprop="name">Kaleem Ullah</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">6,501</span><span title="3 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 gold badges</span><span title="39 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">39</span></span><span class="v-visible-sr">39 silver badges</span><span title="47 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">47</span></span><span class="v-visible-sr">47 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-32331953" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="32331953" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-32331953" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="39425637" id="39425637"></a>
|
||
<div id="answer-39425637" class="answer js-answer" data-answerid="39425637" data-parentid="231767" data-score="65" data-position-on-page="28" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="39425637">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-rkap9fth"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-rkap9fth" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="65">
|
||
65
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-5owvw7hp"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-5owvw7hp" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-39425637" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="39425637" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-pqtv8t2v"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-pqtv8t2v" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/39425637/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-iarxz3bc"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-iarxz3bc" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
Many people use <code>return</code> rather than <code>yield</code>, but in some cases <code>yield</code> can be more efficient and easier to work with.
|
||
</p>
|
||
<p>
|
||
Here is an example which <code>yield</code> is definitely best for:
|
||
</p>
|
||
<blockquote>
|
||
<p>
|
||
<strong>return</strong> (in function)
|
||
</p>
|
||
</blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">import</span> random
|
||
|
||
<span class="hljs-keyword">def</span> <span class="hljs-title function_">return_dates</span>():
|
||
dates = [] <span class="hljs-comment"># With 'return' you need to create a list then return it</span>
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">5</span>):
|
||
date = random.choice([<span class="hljs-string">"1st"</span>, <span class="hljs-string">"2nd"</span>, <span class="hljs-string">"3rd"</span>, <span class="hljs-string">"4th"</span>, <span class="hljs-string">"5th"</span>, <span class="hljs-string">"6th"</span>, <span class="hljs-string">"7th"</span>, <span class="hljs-string">"8th"</span>, <span class="hljs-string">"9th"</span>, <span class="hljs-string">"10th"</span>])
|
||
dates.append(date)
|
||
<span class="hljs-keyword">return</span> dates
|
||
</code></pre>
|
||
<blockquote>
|
||
<p>
|
||
<strong>yield</strong> (in function)
|
||
</p>
|
||
</blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">yield_dates</span>():
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">5</span>):
|
||
date = random.choice([<span class="hljs-string">"1st"</span>, <span class="hljs-string">"2nd"</span>, <span class="hljs-string">"3rd"</span>, <span class="hljs-string">"4th"</span>, <span class="hljs-string">"5th"</span>, <span class="hljs-string">"6th"</span>, <span class="hljs-string">"7th"</span>, <span class="hljs-string">"8th"</span>, <span class="hljs-string">"9th"</span>, <span class="hljs-string">"10th"</span>])
|
||
<span class="hljs-keyword">yield</span> date <span class="hljs-comment"># 'yield' makes a generator automatically which works</span>
|
||
<span class="hljs-comment"># in a similar way. This is much more efficient.</span>
|
||
</code></pre>
|
||
<blockquote>
|
||
<p>
|
||
<strong>Calling functions</strong>
|
||
</p>
|
||
</blockquote>
|
||
<pre class="lang-py s-code-block"><code class="hljs language-python">dates_list = return_dates()
|
||
<span class="hljs-built_in">print</span>(dates_list)
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> dates_list:
|
||
<span class="hljs-built_in">print</span>(i)
|
||
|
||
dates_generator = yield_dates()
|
||
<span class="hljs-built_in">print</span>(dates_generator)
|
||
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> dates_generator:
|
||
<span class="hljs-built_in">print</span>(i)
|
||
</code></pre>
|
||
<p>
|
||
Both functions do the same thing, but <code>yield</code> uses three lines instead of five and has one less variable to worry about.
|
||
</p>
|
||
<blockquote>
|
||
<blockquote>
|
||
<p>
|
||
<strong>This is the result from the code:</strong>
|
||
</p>
|
||
</blockquote>
|
||
</blockquote>
|
||
<p>
|
||
<a href="https://i.stack.imgur.com/iUFNJ.png" rel="noreferrer"><img src="https://i.stack.imgur.com/iUFNJ.png" alt="Output" /></a>
|
||
</p>
|
||
<p>
|
||
As you can see both functions do the same thing. The only difference is <code>return_dates()</code> gives a list and <code>yield_dates()</code> gives a generator.
|
||
</p>
|
||
<p>
|
||
A real life example would be something like reading a file line by line or if you just want to make a generator.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="39425637">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/39425637" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-28" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-28">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-28">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-28" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 4.0">CC BY-SA 4.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/39425637/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-39425637" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-cpx9uisq">Follow</button>
|
||
<div id="--stacks-s-tooltip-cpx9uisq" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
<a href="/posts/39425637/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2018-05-20 11:02:52Z" class="relativetime">May 20, 2018 at 11:02</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/63550/peter-mortensen">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/RIZKi.png?s=64&g=1" alt="Peter Mortensen's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/63550/peter-mortensen">Peter Mortensen</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score 30,619" dir="ltr">30.6k</span><span title="21 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">21</span></span><span class="v-visible-sr">21 gold badges</span><span title="104 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">104</span></span><span class="v-visible-sr">104 silver badges</span><span title="125 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">125</span></span><span class="v-visible-sr">125 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info user-hover">
|
||
<div class="user-action-time">
|
||
answered <span title="2016-09-10 11:37:25Z" class="relativetime">Sep 10, 2016 at 11:37</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/5177604/tom-fuller">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/3f8d9d1b1e5cd8c23552b2b6e1f9f8f0?s=64&d=identicon&r=PG&f=1" alt="Tom Fuller's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/5177604/tom-fuller">Tom Fuller</a><span class="d-none" itemprop="name">Tom Fuller</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">5,081</span><span title="6 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">6</span></span><span class="v-visible-sr">6 gold badges</span><span title="32 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">32</span></span><span class="v-visible-sr">32 silver badges</span><span title="42 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">42</span></span><span class="v-visible-sr">42 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-39425637" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="39425637" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-39425637" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="33788856" id="33788856"></a>
|
||
<div id="answer-33788856" class="answer js-answer" data-answerid="33788856" data-parentid="231767" data-score="55" data-position-on-page="29" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="33788856">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-t7icfucx"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-t7icfucx" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="55">
|
||
55
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-yoewx4md"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-yoewx4md" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-33788856" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="33788856" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-cbt6f04v"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-cbt6f04v" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/33788856/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-5jfhm8ph"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-5jfhm8ph" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
The <code>yield</code> keyword simply collects returning results. Think of <code>yield</code> like <code>return +=</code>
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="33788856">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/33788856" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-29" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-29">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-29">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-29" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/33788856/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-33788856" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-kv1dzqwt">Follow</button>
|
||
<div id="--stacks-s-tooltip-kv1dzqwt" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
<a href="/posts/33788856/revisions" title="show all edits to this post" class="js-gps-track" data-gps-track="post.click({ item: 4, priv: 0, post_type: 2 })">edited <span title="2016-04-23 03:16:19Z" class="relativetime">Apr 23, 2016 at 3:16</span></a>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/4907496/phillip">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/lz1fz.png?s=64&g=1" alt="Phillip's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details">
|
||
<a href="/users/4907496/phillip">Phillip</a>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">2,165</span><span title="3 gold badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">3</span></span><span class="v-visible-sr">3 gold badges</span><span title="25 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">25</span></span><span class="v-visible-sr">25 silver badges</span><span title="40 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">40</span></span><span class="v-visible-sr">40 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2015-11-18 19:37:29Z" class="relativetime">Nov 18, 2015 at 19:37</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/5069117/bahtiyar-%c3%96zdere">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://i.stack.imgur.com/l5T2i.jpg?s=64&g=1" alt="Bahtiyar Özdere's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/5069117/bahtiyar-%c3%96zdere">Bahtiyar Özdere</a><span class="d-none" itemprop="name">Bahtiyar Özdere</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">1,734</span><span title="16 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">16</span></span><span class="v-visible-sr">16 silver badges</span><span title="20 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">20</span></span><span class="v-visible-sr">20 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-33788856" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="33788856" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-33788856" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><a name="30341713" id="30341713"></a>
|
||
<div id="answer-30341713" class="answer js-answer" data-answerid="30341713" data-parentid="231767" data-score="52" data-position-on-page="30" data-highest-scored="0" data-question-has-accepted-highest-score="1" itemprop="suggestedAnswer" itemscope="itemscope" itemtype="https://schema.org/Answer">
|
||
<div class="post-layout">
|
||
<div class="votecell post-layout--left">
|
||
<div class="js-voting-container d-flex jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="30341713">
|
||
<button class="js-vote-up-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Up vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-3oaxxa8i"><svg aria-hidden="true" class="svg-icon iconArrowUpLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 25h32L18 9 2 25Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-3oaxxa8i" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-vote-count flex--item d-flex fd-column ai-center fc-black-500 fs-title" itemprop="upvoteCount" data-value="52">
|
||
52
|
||
</div><button class="js-vote-down-btn flex--item s-btn s-btn__unset c-pointer" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-pressed="false" aria-label="Down vote" data-selected-classes="fc-theme-primary" data-unselected-classes="" aria-describedby="--stacks-s-tooltip-2ptl40u3"><svg aria-hidden="true" class="svg-icon iconArrowDownLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="M2 11h32L18 27 2 11Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-2ptl40u3" class="s-popover s-popover__tooltip" role="tooltip">
|
||
This answer is not useful
|
||
<div class="s-popover--arrow"></div>
|
||
</div><button class="js-saves-btn s-btn s-btn__unset c-pointer py4" id="saves-btn-30341713" data-controller="s-tooltip" data-s-tooltip-placement="right" data-s-popover-placement="" aria-pressed="false" data-post-id="30341713" data-post-type-id="2" data-user-privilege-for-post-click="0" aria-controls="" data-s-popover-auto-show="false" aria-describedby="--stacks-s-tooltip-yao4cizq"><svg aria-hidden="true" class="fc-theme-primary-500 js-saves-btn-selected d-none svg-icon iconBookmark" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg> <svg aria-hidden="true" class="js-saves-btn-unselected svg-icon iconBookmarkAlt" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="m9 10.6 4 2.66V3H5v10.26l4-2.66ZM3 17V3c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v14l-6-4-6 4Z"></path></svg></button>
|
||
<div id="--stacks-s-tooltip-yao4cizq" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Save this answer.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
<div class="js-accepted-answer-indicator flex--item fc-green-700 py6 mtn8 d-none" data-s-tooltip-placement="right" title="Loading when this answer was accepted…" tabindex="0" role="note" aria-label="Accepted">
|
||
<div class="ta-center">
|
||
<svg aria-hidden="true" class="svg-icon iconCheckmarkLg" width="36" height="36" viewbox="0 0 36 36">
|
||
<path d="m6 14 8 8L30 6v8L14 30l-8-8v-8Z"></path></svg>
|
||
</div>
|
||
</div><a class="js-post-issue flex--item s-btn s-btn__unset c-pointer py6 mx-auto" href="/posts/30341713/timeline" data-shortcut="T" data-ks-title="timeline" data-controller="s-tooltip" data-s-tooltip-placement="right" aria-label="Timeline" aria-describedby="--stacks-s-tooltip-mrr7wtqu"><svg aria-hidden="true" class="mln2 mr0 svg-icon iconHistory" width="19" height="18" viewbox="0 0 19 18">
|
||
<path d="M3 9a8 8 0 1 1 3.73 6.77L8.2 14.3A6 6 0 1 0 5 9l3.01-.01-4 4-4-4h3L3 9Zm7-4h1.01L11 9.36l3.22 2.1-.6.93L10 10V5Z"></path></svg></a>
|
||
<div id="--stacks-s-tooltip-mrr7wtqu" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Show activity on this post.
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="answercell post-layout--right">
|
||
<div class="s-prose js-post-body" itemprop="text">
|
||
<p>
|
||
<code>yield</code> is like a return element for a function. The difference is, that the <code>yield</code> element turns a function into a generator. A generator behaves just like a function until something is 'yielded'. The generator stops until it is next called, and continues from exactly the same point as it started. You can get a sequence of all the 'yielded' values in one, by calling <code>list(generator())</code>.
|
||
</p>
|
||
</div>
|
||
<div class="mt24">
|
||
<div class="d-flex fw-wrap ai-start jc-end gs8 gsy">
|
||
<div class="flex--item mr16" style="flex: 1 1 100px;">
|
||
<div class="js-post-menu pt2" data-post-id="30341713">
|
||
<div class="d-flex gs8 s-anchors s-anchors__muted fw-wrap">
|
||
<div class="flex--item">
|
||
<a href="/a/30341713" rel="nofollow" itemprop="url" class="js-share-link js-gps-track" title="Short permalink to this answer" data-gps-track="post.click({ item: 2, priv: 0, post_type: 2 })" data-controller="se-share-sheet s-popover" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start" aria-controls="se-share-sheet-30" data-action="s-popover#toggle se-share-sheet#preventNavigation s-popover:show->se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" aria-expanded="false">Share</a>
|
||
<div class="s-popover z-dropdown s-anchors s-anchors__default" style="width: unset; max-width: 28em;" id="se-share-sheet-30">
|
||
<div class="s-popover--arrow"></div>
|
||
<div>
|
||
<label class="js-title fw-bold" for="share-sheet-input-se-share-sheet-30">Share a link to this answer</label>
|
||
</div>
|
||
<div class="my8">
|
||
<input type="text" id="share-sheet-input-se-share-sheet-30" class="js-input s-input wmn3 sm:wmn-initial bc-black-200 bg-white fc-dark" readonly="readonly" />
|
||
</div>
|
||
<div class="d-flex jc-space-between ai-center mbn4">
|
||
<button class="js-copy-link-btn s-btn s-btn__link js-gps-track" data-gps-track="">Copy link</button><a href="https://creativecommons.org/licenses/by-sa/3.0/" rel="license" class="js-license s-block-link w-auto" target="_blank" title="The current license for this post: CC BY-SA 3.0">CC BY-SA 3.0</a>
|
||
<div class="js-social-container d-none"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="flex--item">
|
||
<a href="/posts/30341713/edit" class="js-suggest-edit-post js-gps-track" data-gps-track="post.click({ item: 6, priv: 0, post_type: 2 })" title="">Improve this answer</a>
|
||
</div>
|
||
<div class="flex--item">
|
||
<button type="button" id="btnFollowPost-30341713" class="s-btn s-btn__link js-follow-post js-follow-answer js-gps-track" data-gps-track="post.click({ item: 14, priv: 0, post_type: 2 })" data-controller="s-tooltip" data-s-tooltip-placement="bottom" data-s-popover-placement="bottom" aria-controls="" aria-describedby="--stacks-s-tooltip-g7j8sme1">Follow</button>
|
||
<div id="--stacks-s-tooltip-g7j8sme1" class="s-popover s-popover__tooltip" role="tooltip">
|
||
Follow this answer to receive notifications
|
||
<div class="s-popover--arrow"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="js-menu-popup-container"></div>
|
||
</div>
|
||
</div>
|
||
<div class="post-signature flex--item fl0">
|
||
<div class="user-info">
|
||
<div class="user-action-time">
|
||
answered <span title="2015-05-20 06:19:32Z" class="relativetime">May 20, 2015 at 6:19</span>
|
||
</div>
|
||
<div class="user-gravatar32">
|
||
<a href="/users/4884103/will-dereham">
|
||
<div class="gravatar-wrapper-32">
|
||
<img src="https://www.gravatar.com/avatar/d816ef3e01a9c231b01ca20b271f1920?s=64&d=identicon&r=PG&f=1" alt="Will Dereham's user avatar" width="32" height="32" class="bar-sm" />
|
||
</div></a>
|
||
</div>
|
||
<div class="user-details" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person">
|
||
<a href="/users/4884103/will-dereham">Will Dereham</a><span class="d-none" itemprop="name">Will Dereham</span>
|
||
<div class="-flair">
|
||
<span class="reputation-score" title="reputation score " dir="ltr">986</span><span title="10 silver badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">10</span></span><span class="v-visible-sr">10 silver badges</span><span title="33 bronze badges" aria-hidden="true"><img src="https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27" /><span class="badgecount">33</span></span><span class="v-visible-sr">33 bronze badges</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="post-layout--right js-post-comments-component">
|
||
<div id="comments-30341713" class="comments js-comments-container bt bc-black-075 mt12 dno" data-post-id="30341713" data-min-length="15">
|
||
<ul class="comments-list js-comments-list" data-remaining-comments-count="0" data-canpost="false" data-cansee="true" data-comments-unavailable="false" data-addlink-disabled="true"></ul>
|
||
</div>
|
||
<div id="comments-link-30341713" data-rep="50" data-anon="true">
|
||
<a class="js-add-link comments-link disabled-link" title="Use comments to ask for more information or suggest improvements. Avoid comments like “+1” or “thanks”." href="#" role="button">Add a comment</a> <span class="js-link-separator dno"> | </span> <a class="js-show-link comments-link dno" title="Expand to show all comments on this post" href="#" onclick="" role="button"></a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="s-pagination site1 themed pager-answers">
|
||
<div class="s-pagination--item is-selected" aria-current=""page"">
|
||
1
|
||
</div><a class="s-pagination--item js-pagination-item" href="/questions/231767/what-does-the-yield-keyword-do-in-python?page=2&tab=scoredesc#tab-top" rel="" title="Go to page 2">2</a> <a class="s-pagination--item js-pagination-item" href="/questions/231767/what-does-the-yield-keyword-do-in-python?page=2&tab=scoredesc#tab-top" rel="next" title="Go to page 2">Next</a>
|
||
</div>
|
||
<aside class="s-notice s-notice__info post-notice js-post-notice mb16" role="status">
|
||
<div class="d-flex fd-column fw-nowrap">
|
||
<div class="d-flex fw-nowrap">
|
||
<div class="flex--item mr8">
|
||
<svg aria-hidden="true" class="svg-icon iconFire" width="18" height="18" viewbox="0 0 18 18">
|
||
<path opacity=".6" d="M13.18 9c-.8.33-1.46.6-1.97 1.3A9.21 9.21 0 0 0 10 13.89a10 10 0 0 0 1.32-.8 2.53 2.53 0 0 1-.63 2.91h.78a3 3 0 0 0 1.66-.5 4.15 4.15 0 0 0 1.26-1.61c.4-.96.47-1.7.55-2.73.05-1.24-.1-2.49-.46-3.68a2 2 0 0 1-.4.91 2.1 2.1 0 0 1-.9.62Z" fill="#FF6700"></path>
|
||
<path d="M10.4 12.11a7.1 7.1 0 0 1 .78-1.76c.3-.47.81-.8 1.37-1.08 0 0-.05-3.27-1.55-5.27-1.5-2-3.37-2.75-4.95-2.61 0 0 4.19 2.94 1.18 5.67-2.14 1.92-3.64 3.81-3.1 5.94a4.14 4.14 0 0 0 3.1 3 4.05 4.05 0 0 1 1.08-3.89C9.42 10.92 8 9.79 8 9.79c.67.02 1.3.28 1.81.72a2 2 0 0 1 .58 1.6Z" fill="#EF2E2E"></path></svg>
|
||
</div>
|
||
<div class="flex--item wmn0 fl1 lh-lg">
|
||
<div class="flex--item fl1 lh-lg">
|
||
<b><a href="/help/privileges/protect-questions">Highly active question</a></b>. Earn 10 reputation (not counting the <a href="https://meta.stackexchange.com/questions/141648/what-is-the-association-bonus-and-how-does-it-work">association bonus</a>) in order to answer this question. The reputation requirement helps protect this question from spam and non-answer activity.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
<h2 class="bottom-notice" data-loc="1"></h2>
|
||
<div>
|
||
<h2 class="bottom-notice" data-loc="1">
|
||
Not the answer you're looking for? Browse other questions tagged
|
||
</h2>
|
||
</div>
|
||
<ul class="ml0 list-ls-none js-post-tag-list-wrapper d-inline">
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python" class="post-tag" title="show questions tagged 'python'" aria-label="show questions tagged 'python'" rel="tag" aria-labelledby="python-container">python</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python-3.x" class="post-tag" title="show questions tagged 'python-3.x'" aria-label="show questions tagged 'python-3.x'" rel="tag" aria-labelledby="python-3.x-container">python-3.x</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/generator" class="post-tag" title="show questions tagged 'generator'" aria-label="show questions tagged 'generator'" rel="tag" aria-labelledby="generator-container">generator</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/python-2.x" class="post-tag" title="show questions tagged 'python-2.x'" aria-label="show questions tagged 'python-2.x'" rel="tag" aria-labelledby="python-2.x-container">python-2.x</a>
|
||
</li>
|
||
<li class="d-inline mr4 js-post-tag-list-item">
|
||
<a href="/questions/tagged/yield" class="post-tag" title="show questions tagged 'yield'" aria-label="show questions tagged 'yield'" rel="tag" aria-labelledby="yield-container">yield</a>
|
||
</li>
|
||
</ul>or <a href="/questions/ask">ask your own question</a>.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="sidebar" class="show-votes" role="complementary" aria-label="sidebar">
|
||
<div class="s-sidebarwidget s-sidebarwidget__yellow s-anchors s-anchors__grayscale mb16" data-tracker="cb=1">
|
||
<ul class="d-block p0 m0">
|
||
<li class="s-sidebarwidget--header s-sidebarwidget__small-bold-text d-flex fc-black-600 d:fc-black-900 bb bbw1">The Overflow Blog
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<svg aria-hidden="true" class="va-text-top svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg>
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://stackoverflow.blog/2022/11/22/heres-what-its-like-to-develop-vr-at-meta-ep-508/?cb=1" class="js-gps-track" data-ga="["community bulletin board","The Overflow Blog","https://stackoverflow.blog/2022/11/22/heres-what-its-like-to-develop-vr-at-meta-ep-508/",null,null]" data-gps-track="communitybulletin.click({ priority: 1, position: 0 })">Here’s what it’s like to develop VR at Meta (Ep. 508)</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<svg aria-hidden="true" class="va-text-top svg-icon iconPencilSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="m11.1 1.71 1.13 1.12c.2.2.2.51 0 .71L11.1 4.7 9.21 2.86l1.17-1.15c.2-.2.51-.2.71 0ZM2 10.12l6.37-6.43 1.88 1.88L3.88 12H2v-1.88Z"></path></svg>
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://stackoverflow.blog/2022/11/23/why-writing-by-hand-is-still-the-best-way-to-retain-information/?cb=1" class="js-gps-track" data-ga="["community bulletin board","The Overflow Blog","https://stackoverflow.blog/2022/11/23/why-writing-by-hand-is-still-the-best-way-to-retain-information/",null,null]" data-gps-track="communitybulletin.click({ priority: 1, position: 1 })">Why writing by hand is still the best way to retain information</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--header s-sidebarwidget__small-bold-text d-flex fc-black-600 d:fc-black-900 bb bbw1">Featured on Meta
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" />
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://meta.stackexchange.com/questions/383855/the-windows-phone-se-site-has-been-archived?cb=1" class="js-gps-track" data-ga="["community bulletin board","Featured on Meta","https://meta.stackexchange.com/questions/383855/the-windows-phone-se-site-has-been-archived",null,null]" data-gps-track="communitybulletin.click({ priority: 3, position: 2 })">The Windows Phone SE site has been archived</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" />
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://meta.stackexchange.com/questions/383963/stack-gives-back-to-open-source-2022?cb=1" class="js-gps-track" data-ga="["community bulletin board","Featured on Meta","https://meta.stackexchange.com/questions/383963/stack-gives-back-to-open-source-2022",null,null]" data-gps-track="communitybulletin.click({ priority: 3, position: 3 })">Stack Gives Back to Open Source 2022</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" />
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://meta.stackoverflow.com/questions/254311/the-collapse-tag-is-being-burninated?cb=1" class="js-gps-track" data-ga="["community bulletin board","Featured on Meta","https://meta.stackoverflow.com/questions/254311/the-collapse-tag-is-being-burninated",null,null]" data-gps-track="communitybulletin.click({ priority: 6, position: 4 })">The [collapse] tag is being burninated</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" />
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://meta.stackoverflow.com/questions/421038/the-ask-wizard-2022-has-graduated?cb=1" class="js-gps-track" data-ga="["community bulletin board","Featured on Meta","https://meta.stackoverflow.com/questions/421038/the-ask-wizard-2022-has-graduated",null,null]" data-gps-track="communitybulletin.click({ priority: 6, position: 5 })">The Ask Wizard (2022) has graduated</a>
|
||
</div>
|
||
</li>
|
||
<li class="s-sidebarwidget--item d-flex px16">
|
||
<div class="flex--item1 fl-shrink0">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" />
|
||
</div>
|
||
<div class="flex--item wmn0 ow-break-word">
|
||
<a href="https://meta.stackoverflow.com/questions/421619/2022-community-moderator-election-results?cb=1" class="js-gps-track" data-ga="["community bulletin board","Featured on Meta","https://meta.stackoverflow.com/questions/421619/2022-community-moderator-election-results",null,null]" data-gps-track="communitybulletin.click({ priority: 6, position: 6 })">2022 Community Moderator Election Results</a>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="js-zone-container zone-container-sidebar">
|
||
<div id="dfp-tsb" class="everyonelovesstackoverflow everyoneloves__top-sidebar" data-dfp-zone="true" style="min-height: auto; height: auto; display: none;" data-google-query-id="CIvxo5rDxvsCFcJqfQodrp4Lxg">
|
||
<div id="google_ads_iframe_/248424177/stackoverflow.com/sb/question-pages_0__container__" style="border: 0pt none; width: 300px; height: 0px;"></div>
|
||
</div>
|
||
<div class="js-report-ad-button-container" style="width: 300px"></div>
|
||
</div>
|
||
<div class="js-zone-container zone-container-sidebar">
|
||
<div id="dfp-msb" class="everyonelovesstackoverflow everyoneloves__mid-sidebar" data-dfp-zone="true" style="min-height: auto; height: auto; display: none;" data-google-query-id="CNfyo5rDxvsCFZQQcgodyNoMVA">
|
||
<div id="google_ads_iframe_/248424177/stackoverflow.com/msb/question-pages_0__container__" style="border: 0pt none; width: 300px; height: 0px;"></div>
|
||
</div>
|
||
<div class="js-report-ad-button-container" style="width: 300px"></div>
|
||
</div>
|
||
<div id="hireme"></div>
|
||
<div class="module sidebar-linked">
|
||
<h4 id="h-linked">
|
||
Linked
|
||
</h4>
|
||
<div class="linked" data-tracker="lq=1">
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 16483625, position: 0 })">
|
||
<a href="https://stackoverflow.com/q/16483625?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
86
|
||
</div></a> <a href="https://stackoverflow.com/questions/16483625/for-x-in-y-how-does-this-work?noredirect=1&lq=1" class="question-hyperlink">for x in y(): how does this work?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 46440267, position: 1 })">
|
||
<a href="https://stackoverflow.com/q/46440267?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
22
|
||
</div></a> <a href="https://stackoverflow.com/questions/46440267/how-two-consecutive-yield-statement-work-in-python?noredirect=1&lq=1" class="question-hyperlink">How two consecutive yield statement work in python?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 12068827, position: 2 })">
|
||
<a href="https://stackoverflow.com/q/12068827?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
19
|
||
</div></a> <a href="https://stackoverflow.com/questions/12068827/what-is-a-yield-statement-in-a-function?noredirect=1&lq=1" class="question-hyperlink">What is a "yield" statement in a function?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 9870565, position: 3 })">
|
||
<a href="https://stackoverflow.com/q/9870565?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
8
|
||
</div></a> <a href="https://stackoverflow.com/questions/9870565/what-does-yield-do-in-python-2-7?noredirect=1&lq=1" class="question-hyperlink">What does yield do in python 2.7?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 23249931, position: 4 })">
|
||
<a href="https://stackoverflow.com/q/23249931?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
25
|
||
</div></a> <a href="https://stackoverflow.com/questions/23249931/trouble-understanding-python-generators?noredirect=1&lq=1" class="question-hyperlink">Trouble understanding python generators</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 15930015, position: 5 })">
|
||
<a href="https://stackoverflow.com/q/15930015?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes default">
|
||
12
|
||
</div></a> <a href="https://stackoverflow.com/questions/15930015/how-does-a-function-in-python-remember-its-values-after-it-returns?noredirect=1&lq=1" class="question-hyperlink">How does a function in Python remember its values after it returns?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 60892053, position: 6 })">
|
||
<a href="https://stackoverflow.com/q/60892053?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
3
|
||
</div></a> <a href="https://stackoverflow.com/questions/60892053/how-generator-expressions-work-internally-in-python?noredirect=1&lq=1" class="question-hyperlink">How Generator expressions work internally in python?</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 19413538, position: 7 })">
|
||
<a href="https://stackoverflow.com/q/19413538?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted default">
|
||
4
|
||
</div></a> <a href="https://stackoverflow.com/questions/19413538/yield-does-not-work-but-return-does?noredirect=1&lq=1" class="question-hyperlink">Yield does not work, but return does</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 50571343, position: 8 })">
|
||
<a href="https://stackoverflow.com/q/50571343?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes default">
|
||
3
|
||
</div></a> <a href="https://stackoverflow.com/questions/50571343/unreachable-yield-still-strangely-affects-function?noredirect=1&lq=1" class="question-hyperlink">Unreachable 'yield' still strangely affects function</a>
|
||
</div>
|
||
<div class="spacer js-gps-track" data-gps-track="linkedquestion.click({ source_post_id: 231767, target_question_id: 56271174, position: 9 })">
|
||
<a href="https://stackoverflow.com/q/56271174?lq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes default">
|
||
4
|
||
</div></a> <a href="https://stackoverflow.com/questions/56271174/what-is-the-difference-between-yield-and-return?noredirect=1&lq=1" class="question-hyperlink">What is the difference between yield and return?</a>
|
||
</div>
|
||
<div class="spacer more ml32 pl16 pt8">
|
||
<a href="https://stackoverflow.com/questions/linked/231767?lq=1">See more linked questions</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="module sidebar-related">
|
||
<h4 id="h-related">
|
||
Related
|
||
</h4>
|
||
<div class="related js-gps-related-questions" data-tracker="rq=1">
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/36901?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
3169
|
||
</div></a> <a href="https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters-in-p?rq=1" class="question-hyperlink">What does ** (double star/asterisk) and * (star/asterisk) do for parameters in Python?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/39476?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
1003
|
||
</div></a> <a href="https://stackoverflow.com/questions/39476/what-is-the-yield-keyword-used-for-in-c?rq=1" class="question-hyperlink">What is the yield keyword used for in C#?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/100003?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
7024
|
||
</div></a> <a href="https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python?rq=1" class="question-hyperlink">What are metaclasses in Python?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/136097?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
4445
|
||
</div></a> <a href="https://stackoverflow.com/questions/136097/classmethod-vs-staticmethod-in-python?rq=1" class="question-hyperlink">@classmethod vs @staticmethod in Python</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/394809?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
7552
|
||
</div></a> <a href="https://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator?rq=1" class="question-hyperlink">Does Python have a ternary conditional operator?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/419163?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
7821
|
||
</div></a> <a href="https://stackoverflow.com/questions/419163/what-does-if-name-main-do?rq=1" class="question-hyperlink">What does if __name__ == "__main__": do?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/522563?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
4929
|
||
</div></a> <a href="https://stackoverflow.com/questions/522563/accessing-the-index-in-for-loops?rq=1" class="question-hyperlink">Accessing the index in 'for' loops</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/1436703?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
3510
|
||
</div></a> <a href="https://stackoverflow.com/questions/1436703/what-is-the-difference-between-str-and-repr?rq=1" class="question-hyperlink">What is the difference between __str__ and __repr__?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/3437059?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
3588
|
||
</div></a> <a href="https://stackoverflow.com/questions/3437059/does-python-have-a-string-contains-substring-method?rq=1" class="question-hyperlink">Does Python have a string 'contains' substring method?</a>
|
||
</div>
|
||
<div class="spacer">
|
||
<a href="https://stackoverflow.com/q/7943751?rq=1" title="Question score (upvotes - downvotes)">
|
||
<div class="answer-votes answered-accepted extra-large">
|
||
1582
|
||
</div></a> <a href="https://stackoverflow.com/questions/7943751/what-is-the-python-3-equivalent-of-python-m-simplehttpserver?rq=1" class="question-hyperlink">What is the Python 3 equivalent of "python -m SimpleHTTPServer"</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="hot-network-questions" class="module tex2jax_ignore">
|
||
<h4>
|
||
<a href="https://stackexchange.com/questions?tab=hot" class="js-gps-track s-link s-link__inherit" data-gps-track="posts_hot_network.click({ item_type:1, location:11 })">Hot Network Questions</a>
|
||
</h4>
|
||
<ul>
|
||
<li>
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://rpg.stackexchange.com/questions/202991/can-i-choose-not-to-multiply-my-damage-on-a-critical-hit" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:122 }); posts_hot_network.click({ item_type:2, location:11 })">Can I choose not to multiply my damage on a critical hit?</a>
|
||
</li>
|
||
<li>
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://worldbuilding.stackexchange.com/questions/238477/how-could-bioluminescence-work-as-a-flashlight" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:579 }); posts_hot_network.click({ item_type:2, location:11 })">How Could Bioluminescence work as a Flashlight?</a>
|
||
</li>
|
||
<li>
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://diy.stackexchange.com/questions/261105/range-hood-galvanized-pipe-installation-code" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:73 }); posts_hot_network.click({ item_type:2, location:11 })">Range Hood Galvanized Pipe - Installation Code</a>
|
||
</li>
|
||
<li>
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://academia.stackexchange.com/questions/190859/should-i-pick-a-time-if-a-professor-asks-me-to" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:415 }); posts_hot_network.click({ item_type:2, location:11 })">Should I pick a time if a professor asks me to?</a>
|
||
</li>
|
||
<li>
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://workplace.stackexchange.com/questions/188730/what-should-i-do-when-my-company-threatens-to-give-a-bad-review-to-my-university" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:423 }); posts_hot_network.click({ item_type:2, location:11 })">What should I do when my company threatens to give a bad review to my university if I quit my job?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://gis.stackexchange.com/questions/445801/calculating-statistics-of-points-within-polygons-of-the-same-criterion-in-qgis" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:79 }); posts_hot_network.click({ item_type:2, location:11 })">Calculating statistics of points within polygons of the same criterion in QGIS</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://mechanics.stackexchange.com/questions/90383/should-i-lube-the-engine-block-bore-before-inserting-a-metal-tube" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:224 }); posts_hot_network.click({ item_type:2, location:11 })">Should i lube the engine block bore before inserting a metal tube?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://physics.stackexchange.com/questions/737808/in-relativity-how-do-clocks-get-out-of-sync-on-a-physical-level" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:151 }); posts_hot_network.click({ item_type:2, location:11 })">In relativity, how do clocks get out of sync on a physical level?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://scifi.stackexchange.com/questions/269668/early-2010s-steampunk-series-aired-in-sy-fy-channel-about-a-girl-fighting-a-cult" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:186 }); posts_hot_network.click({ item_type:2, location:11 })">Early 2010s Steampunk series aired in Sy-fy channel about a girl fighting a cult</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://diy.stackexchange.com/questions/260990/can-a-14-awg-pigtail-be-used-with-a-smart-switch-with-a-20-amp-breaker" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:73 }); posts_hot_network.click({ item_type:2, location:11 })">Can a 14 AWG pigtail be used with a smart switch with a 20 amp breaker?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://superuser.com/questions/1754385/how-to-increment-a-value-in-a-function-in-powershell" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:3 }); posts_hot_network.click({ item_type:2, location:11 })">How to increment a value in a function in Powershell?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://rpg.stackexchange.com/questions/202996/can-the-circle-of-wildfire-druids-enhanced-bond-give-the-ability-to-have-multi" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:122 }); posts_hot_network.click({ item_type:2, location:11 })">Can the Circle Of Wildfire druid's Enhanced Bond, give the ability to have multiple origin for the multi ray spell type?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://electronics.stackexchange.com/questions/643657/simple-op-amp-comparator-circuit-not-behaving-as-expected" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:135 }); posts_hot_network.click({ item_type:2, location:11 })">Simple op-amp comparator circuit not behaving as expected</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://physics.stackexchange.com/questions/738000/is-there-a-reliable-quantum-theory-of-gravitation" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:151 }); posts_hot_network.click({ item_type:2, location:11 })">Is there a reliable quantum theory of gravitation?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://pets.stackexchange.com/questions/37242/sizing-a-cat-door" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:518 }); posts_hot_network.click({ item_type:2, location:11 })">Sizing a cat door</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://skeptics.stackexchange.com/questions/54003/are-20-of-automobile-drivers-under-the-influence-of-marijuana" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:212 }); posts_hot_network.click({ item_type:2, location:11 })">Are 20% of automobile drivers under the influence of marijuana?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://law.stackexchange.com/questions/86583/why-dont-people-who-are-untruthful-during-jury-selection-get-held-in-contempt-o" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:617 }); posts_hot_network.click({ item_type:2, location:11 })">Why don't people who are untruthful during jury selection get held in contempt of court?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://stats.stackexchange.com/questions/596727/how-many-datapoints-are-enough-for-a-regression-model-to-predict-with-reasoanble" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:65 }); posts_hot_network.click({ item_type:2, location:11 })">How many datapoints are enough for a regression model to predict with reasoanble (say 88%-92%) accuracy?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://softwareengineering.stackexchange.com/questions/442393/how-to-store-a-fixed-length-array-in-a-database" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:131 }); posts_hot_network.click({ item_type:2, location:11 })">How to store a fixed length array in a database</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://literature.stackexchange.com/questions/23539/short-story-about-a-woman-saving-up-to-buy-a-gift" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:668 }); posts_hot_network.click({ item_type:2, location:11 })">Short Story About a Woman Saving up to Buy a Gift?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://rpg.stackexchange.com/questions/202976/conjure-woodland-beings-polymorph" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:122 }); posts_hot_network.click({ item_type:2, location:11 })">Conjure Woodland Beings + Polymorph</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://diy.stackexchange.com/questions/260935/how-can-i-heat-my-home-further-when-circuit-breakers-are-already-tripping" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:73 }); posts_hot_network.click({ item_type:2, location:11 })">How can I heat my home further when circuit breakers are already tripping?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://mathoverflow.net/questions/435122/why-do-grothendieck-topologies-used-in-algebraic-geometry-typically-involve-fini" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:504 }); posts_hot_network.click({ item_type:2, location:11 })">Why do Grothendieck topologies used in algebraic geometry typically involve finiteness conditions?</a>
|
||
</li>
|
||
<li class="js-hidden" style="">
|
||
<img src="https://cdn.sstatic.net/Img/favicons-sprite16.png?v=22475cccbf39" /> <a href="https://aviation.stackexchange.com/questions/96063/why-does-this-v-22s-rotors-rotate-clockwise-and-anti-clockwise-the-right-and-t" class="js-gps-track question-hyperlink mb0" data-gps-track="site.switch({ item_type:11, target_site:528 }); posts_hot_network.click({ item_type:2, location:11 })">Why does this V-22's rotors rotate clockwise and anti-clockwise (the right and the left rotor respectively)?</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div id="feed-link" class="js-feed-link">
|
||
<a href="/feeds/question/231767" title="Feed of this question and its answers"><svg aria-hidden="true" class="fc-orange-400 svg-icon iconRss" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 1a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3Zm0 1.5c6.9 0 12.5 5.6 12.5 12.5H13C13 9.55 8.45 5 3 5V2.5Zm0 5c4.08 0 7.5 3.41 7.5 7.5H8c0-2.72-2.28-5-5-5V7.5Zm0 5c1.36 0 2.5 1.14 2.5 2.5H3v-2.5Z"></path></svg> Question feed</a>
|
||
</div>
|
||
<aside class="s-modal js-feed-link-modal" tabindex="-1" role="dialog" aria-labelledby="feed-modal-title" aria-describedby="feed-modal-description" aria-hidden="true">
|
||
<div class="s-modal--dialog js-modal-dialog wmx4" role="document" data-controller="se-draggable">
|
||
<h1 class="s-modal--header fw-bold js-first-tabbable c-move" id="feed-modal-title" data-se-draggable-target="handle" tabindex="0">
|
||
Subscribe to RSS
|
||
</h1>
|
||
<div class="d-flex gs4 gsy fd-column">
|
||
<div class="flex--item">
|
||
<label class="d-block s-label c-default" for="feed-url">Question feed</label>
|
||
<p class="s-description mt2" id="feed-modal-description">
|
||
<label class="d-block s-label c-default" for="feed-url">To subscribe to this RSS feed, copy and paste this URL into your RSS reader.</label>
|
||
</p>
|
||
</div>
|
||
<div class="d-flex ps-relative">
|
||
<input class="s-input" type="text" name="feed-url" id="feed-url" readonly="readonly" value="https://stackoverflow.com/feeds/question/231767" /> <svg aria-hidden="true" class="s-input-icon fc-orange-400 svg-icon iconRss" width="18" height="18" viewbox="0 0 18 18">
|
||
<path d="M3 1a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3Zm0 1.5c6.9 0 12.5 5.6 12.5 12.5H13C13 9.55 8.45 5 3 5V2.5Zm0 5c4.08 0 7.5 3.41 7.5 7.5H8c0-2.72-2.28-5-5-5V7.5Zm0 5c1.36 0 2.5 1.14 2.5 2.5H3v-2.5Z"></path></svg>
|
||
</div>
|
||
</div><a class="s-modal--close s-btn s-btn__muted js-modal-close js-last-tabbable" href="#" aria-label="Close"><svg aria-hidden="true" class="svg-icon iconClearSm" width="14" height="14" viewbox="0 0 14 14">
|
||
<path d="M12 3.41 10.59 2 7 5.59 3.41 2 2 3.41 5.59 7 2 10.59 3.41 12 7 8.41 10.59 12 12 10.59 8.41 7 12 3.41Z"></path></svg></a>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
<![CDATA[
|
||
StackExchange.ready(function(){$.get('/posts/231767/ivc/57d4');});
|
||
]]>
|
||
</script> <noscript>
|
||
<div>
|
||
<img src="/posts/231767/ivc/57d4" class="dno" alt="" width="0" height="0" />
|
||
</div></noscript>
|
||
<div style="display:none" id="js-codeblock-lang">
|
||
lang-py
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
<![CDATA[
|
||
;(()=>{"use strict";var __webpack_modules__={23:(e,t,s)=>{s.d(t,{Z7:()=>l,eq:()=>n,kG:()=>r});const a=/^\/tags\//.test(location.pathname)||/^\/questions\/tagged\//.test(location.pathname)?"tag-pages":/^\/$/.test(location.pathname)||/^\/home/.test(location.pathname)?"home-page":"question-pages";let i=location.hostname;const o={slots:{lb:[[728,90]],mlb:[[728,90]],smlb:[[728,90]],bmlb:[[728,90]],sb:e=>"dfp-tsb"===e?[[300,250],[300,600]]:[[300,250]],"tag-sponsorship":[[730,135]],"mobile-below-question":[[320,50],[300,250]],msb:[[300,250],[300,600]],"talent-conversion-tracking":[[1,1]],"site-sponsorship":[[230,60]]},ids:{"dfp-tlb":"lb","dfp-mlb":"mlb","dfp-smlb":"smlb","dfp-bmlb":"bmlb","dfp-tsb":"sb","dfp-isb":"sb","dfp-tag":"tag-sponsorship","dfp-msb":"msb","dfp-sspon":"site-sponsorship","dfp-m-aq":"mobile-below-question"},idsToExcludeFromAdReports:["dfp-sspon"]};function r(){return Object.keys(o.ids)}function n(e){return o.idsToExcludeFromAdReports.indexOf(e)<0}function l(e){var t=e.split("_")[0];const s=o.ids[t];let r=o.slots[s];return"function"==typeof r&&(r=r(t)),{path:`/248424177/${i}/${s}/${a}`,sizes:r,zone:s}}},865:(e,t,s)=>{function a(e){return"string"==typeof e?document.getElementById(e):e}function i(e){return!!(e=a(e))&&"none"===getComputedStyle(e).display}function o(e){return!i(e)}function r(e){return!!e}function n(e){return/^\s*$/.test(a(e).innerHTML)}function l(e){const{style:t}=e;t.height=t.maxHeight=t.minHeight="auto",t.display="none"}function d(e){const{style:t}=e;t.height=t.maxHeight=t.minHeight="auto",t.display="none",[].forEach.call(e.children,d)}function c(e){const{style:t}=e;t.height=t.maxHeight=t.minHeight="auto",t.removeProperty("display")}function p(e){const t=document.createElement("script");t.src=e,document.body.appendChild(t)}function g(e){return s=e,(t=[]).push=function(e){return s(),delete this.push,this.push(e)},t;var t,s}function h(e){let t="function"==typeof HTMLTemplateElement;var s=document.createElement(t?"template":"div");return e=e.trim(),s.innerHTML=e,t?s.content.firstChild:s.firstChild}s.d(t,{$Z:()=>c,Bv:()=>h,Gx:()=>p,Nj:()=>a,QZ:()=>g,cf:()=>l,pn:()=>o,wo:()=>d,xb:()=>n,xj:()=>i,yb:()=>r})},763:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{t:()=>AdReports});var _common_helper__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(865),_console__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(276),_ad_units__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(23);class AdReports{constructor(e,t){if(this.googletag=e,this.cam=t,this.allowedFileTypes=["image/png","image/jpg","image/jpeg"],this.ignoreValidation=!1,this.cam=t,this.callOnButtonClick=e=>this.onButtonClick(e),this.googletag.pubads().addEventListener("slotRenderEnded",e=>this.handleSlotRendered(e)),Array.isArray(t.slotsRenderedEvents))for(var s=0;s<t.slotsRenderedEvents.length;s++)this.handleSlotRendered(t.slotsRenderedEvents[s])}handleSlotRendered(e){if(e&&e.slot&&!e.isEmpty&&(e.creativeId||e.lineItemId||!e.isEmpty)){var t=e.slot.getSlotElementId();if(t){var s=document.getElementById(t);if(s&&(0,_ad_units__WEBPACK_IMPORTED_MODULE_0__.eq)(t)){var a=s?.closest(".js-zone-container")?.querySelector(".js-report-ad-button-container");a.append(this.createButton(e)),a.style.height="24px"}}}}async onButtonClick(e){e.preventDefault();let t=e.target;const s=t.dataset.modalUrl,a=t.dataset.googleEventData;return await this.loadModal(s,t,a),!1}createButton(e){let t=document.createElement("button");var s=JSON.stringify(e);return t.dataset.googleEventData=s,t.dataset.modalUrl=this.cam.opt.adReportUrl,t.dataset.adUnit=e.slot.getSlotElementId(),t.classList.add("js-report-ad","s-btn","s-btn__link","fs-fine","mt2","float-right"),t.append(document.createTextNode(this.cam.opt.adReportText)),t.removeEventListener("click",this.callOnButtonClick),t.addEventListener("click",this.callOnButtonClick),t}async loadModal(url,$link,googleEventData){try{await window.StackExchange.helpers.loadModal(url,{returnElements:window.$($link)}),this.initForm(googleEventData)}catch(e){var message="",response=e.responseText?eval(`(${e.responseText})`):null;message=response&&response.isLoggedOut?this.cam.opt.adReportLoginExpiredMessage:this.cam.opt.adReportLoginErrorMessage,window.StackExchange.helpers.showToast(message,{type:"danger"})}}removeModal(){window.StackExchange.helpers.closePopups(document.querySelectorAll("."+this.cam.opt.adReportModalClass),"dismiss")}initForm(e,t=!1){this.ignoreValidation=t,this.$form=document.querySelector(".js-ad-report-form"),this.$googleEventData=this.$form.querySelector(".js-json-data"),this.$adReportReasons=this.$form.querySelectorAll(".js-ad-report-reason"),this.$adReportReasonOther=this.$form.querySelector(".js-ad-report-reason-other"),this.$fileUploaderInput=this.$form.querySelector(".js-file-uploader-input"),this.$imageUploader=this.$form.querySelector(".js-image-uploader"),this.$clearImageUpload=this.$form.querySelector(".js-clear-image-upload"),this.$imageUploaderText=this.$form.querySelector(".js-image-uploader-text"),this.$imageUploaderPreview=this.$form.querySelector(".js-image-uploader-preview"),this.$fileErrorMessage=this.$form.querySelector(".js-file-error");const s=this.$form.querySelector(".js-drag-drop-enabled"),a=this.$form.querySelector(".js-drag-drop-disabled");this.$googleEventData.value=e,this.$adReportReasons.forEach((e,t)=>e.addEventListener("change",e=>{this.$adReportReasonOther.classList.toggle("d-none","3"!==e.target.value)})),this.$fileUploaderInput.addEventListener("change",()=>{this.validateFileInput()&&this.updateImagePreview(this.$fileUploaderInput.files)}),this.$clearImageUpload.addEventListener("click",e=>{e.preventDefault(),this.clearImageUpload()});try{this.$fileUploaderInput[0].value="",this.$imageUploader.addEventListener("dragenter dragover dragleave drop",this.preventDefaults),this.$imageUploader.addEventListener("dragenter dragover",this.handleDragStart),this.$imageUploader.addEventListener("dragleave drop",this.handleDragEnd),this.$imageUploader.addEventListener("drop",this.handleDrop)}catch(e){s.classList.add("d-none"),a.classList.remove("d-none")}this.$form.removeEventListener("",this.handleDragEnd),this.$form.addEventListener("submit",async e=>(e.preventDefault(),this.submitForm(),!1))}clearImageUpload(){this.$fileUploaderInput.value="",this.$imageUploaderPreview.setAttribute("src",""),this.$imageUploaderPreview.classList.add("d-none"),this.$clearImageUpload.classList.add("d-none"),this.$imageUploaderText.classList.remove("d-none"),this.$imageUploader.classList.add("p16","ba","bas-dashed","bc-black-100")}preventDefaults(e){e.preventDefault(),e.stopPropagation()}handleDragStart(e){this.$imageUploader.classList.remove("bas-dashed"),this.$imageUploader.classList.add("bas-solid","bc-black-100")}handleDragEnd(e){this.$imageUploader.classList.remove("bas-solid","bc-black-100"),this.$imageUploader.classList.add("bas-dashed")}handleDrop(e){var t=e.originalEvent.dataTransfer.files;FileReader&&t&&1===t.length&&(this.$fileUploaderInput.files=t,this.validateFileInput()&&this.updateImagePreview(t))}setError(e){this.$fileErrorMessage.parentElement.classList.toggle("has-error",e)}updateImagePreview(e){this.$imageUploader.classList.remove("p16","ba","bas-dashed","bc-black-100"),this.$clearImageUpload.classList.remove("d-none"),this.$imageUploaderText.classList.add("d-none");var t=new FileReader;t.onload=e=>{null!=e.target&&(this.$imageUploaderPreview.setAttribute("src",e.target.result),this.$imageUploaderPreview.classList.remove("d-none"))},t.readAsDataURL(e[0])}validateFileInput(){if(this.ignoreValidation)return!0;const e=this.cam.opt.adReportFileTypeErrorMessage,t=this.cam.opt.adReportFileSizeErrorMessage;if(null==this.$fileUploaderInput.files)return!1;var s=this.$fileUploaderInput.files[0];return null==s?(this.setError(!0),!1):this.allowedFileTypes.indexOf(s.type)<0?(this.$fileErrorMessage.textContent=e,this.$fileErrorMessage.classList.remove("d-none"),this.setError(!0),!1):s.size>2097152?(this.$fileErrorMessage.textContent=t,this.$fileErrorMessage.classList.remove("d-none"),this.setError(!0),!1):(this.$fileErrorMessage.classList.add("d-none"),this.setError(!1),!0)}async submitForm(){if(!this.validateFileInput())return!1;this.$form.querySelector("[type=submit]").setAttribute("disabled","true");var e=JSON.parse(this.$googleEventData.value||"{}");e.Reason=parseInt(this.$form.querySelector(".js-ad-report-reason:checked").value,10),e.Description=this.$adReportReasonOther.value,this.$googleEventData.value=JSON.stringify(e);var t=new FormData(this.$form);try{const e=await window.fetch(this.$form.getAttribute("action"),{method:this.$form.getAttribute("method"),body:t,cache:"no-cache"}),a=e.headers.get("content-type")||"",i=await e.text();if(!e.ok)throw new Error("response not valid");if(0===a.indexOf("text/html")){var s=(0,_common_helper__WEBPACK_IMPORTED_MODULE_1__.Bv)(i);const e=s?s.querySelector(".js-modal-content"):null;if(_console__WEBPACK_IMPORTED_MODULE_2__.cM("$popupContent"),_console__WEBPACK_IMPORTED_MODULE_2__.cM(e),!e)throw new Error(`Could not find .js-modal-content in response from ${this.$form.getAttribute("action")}`);document.querySelector(".js-modal-content").replaceWith(e)}else window.StackExchange.helpers.showToast(this.cam.opt.adReportThanksText,{type:"success"}),this.removeModal()}catch(e){window.StackExchange.helpers.showToast(this.cam.opt.adReportErrorText,{type:"danger"})}finally{let e=this.$form.querySelector("[type=submit]");e&&e.removeAttribute("disabled")}}}},276:(e,t,s)=>{function a(...e){}s.d(t,{cM:()=>a})}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var s=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](s,s.exports,__webpack_require__),s.exports}__webpack_require__.d=(e,t)=>{for(var s in t)__webpack_require__.o(t,s)&&!__webpack_require__.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var __webpack_exports__={};(()=>{var e=__webpack_require__(276),t=(e=>(e[e.Above=0]="Above",e[e.Below=1]="Below",e))(t||{});const s=Object.assign({},{"lib":"https://cdn.sstatic.net/clc/js/bundles/gam_loader_script/gam_loader_script.bundle.741.6e0a482112e96aa6b370.min.js","style":null,"u":null,"wa":true,"kt":2000,"tto":true,"h":"clc.stackoverflow.com","allowed":"^(((talent\\.)?stackoverflow)|(blog\\.codinghorror)|(.*\\.googlesyndication)|(serverfault|askubuntu)|([^\\.]+\\.stackexchange))\\.com$","wv":true,"al":false,"abd":true,"cpa_liid":[5882654614],"cpa_cid":[138377597667],"dp":false});var a=__webpack_require__(23),i=__webpack_require__(865),o=__webpack_require__(763);window.cam=new class{constructor(){this.gptImported=!1,this.collapsed={},this.clc_options=s,e.cM("constructor"),this.initGpt(),window.StackExchange.ready(()=>this.init())}init(){if(e.cM("init"),void 0===this.opt)throw new Error("opt not set, required by GAM Loader");this.opt.adReportEnabled?googletag.cmd.push(()=>this.adReports=new o.t(googletag,this)):googletag.cmd.push(()=>this.handleSlotRenderedNoAdReport()),e.cM("setup message handler"),window.addEventListener("message",e=>{this.onmessage(e)})}handleSlotRenderedNoAdReport(){if(googletag.pubads().addEventListener("slotRenderEnded",e=>this.applyExtraMarginBottom(e)),Array.isArray(this.slotsRenderedEvents))for(var e=0;e<this.slotsRenderedEvents.length;e++)this.applyExtraMarginBottom(this.slotsRenderedEvents[e])}onmessage(t){let s="omni";if(t.data&&("string"==typeof t.data||t.data instanceof String))if(0===t.data.indexOf("get-omni-")){e.cM("Recevied get-omni message, sending back omni");var a=t.source,o=this.opt.omni,r="string"==typeof o?o:"";a.postMessage([s,r].join("|"),"*")}else if(0===t.data.indexOf("collapse-")){e.cM("Recevied collapse message, collapse ad iframe"),e.cM(t);for(var n=t.source.window,l=document.getElementsByTagName("IFRAME"),d=0;d<l.length;d++){var c=l[d];if(c.contentWindow==n)return void(0,i.wo)(c.parentElement.parentElement.parentElement)}}else if(0===t.data.indexOf("resize|")){e.cM("Recevied resize message, resize ad iframe"),e.cM(t);let s=this._getFrameByEvent(t),a=t.data.split("|"),i=parseFloat(a[1])+.5;e.cM("New iframe height "+i),s.height=i.toString(),s.parentElement.style.height=i.toString()+"px"}}_getFrameByEvent(e){return Array.from(document.getElementsByTagName("iframe")).filter(t=>t.contentWindow===e.source)[0]}classifyZoneIds(e){const t=e.map(i.Nj).filter(i.yb);return{eligible:t.filter(i.xb).filter(i.pn),ineligible:t.filter(i.xj)}}applyExtraMarginBottom(e){if(e&&e.slot&&!e.isEmpty&&(e.creativeId||e.lineItemId||!e.isEmpty)){var t=e.slot.getSlotElementId();if(t){var s=document.getElementById(t);if(s&&(0,a.eq)(t)){var i=s?.closest(".js-zone-container");i.style.marginBottom="24px"}}}}load(s=(0,a.kG)()){const o=this.opt.tlb_position===t.Above?["dfp-mlb","dfp-smlb"]:["dfp-mlb","dfp-smlb","dfp-tlb"];if(!this.isGptReady())return e.cM("Initializing..."),this.initGpt(),void googletag.cmd.push(()=>this.load(s));e.cM("Attempting to load ads into ids: ",s);const{eligible:r,ineligible:n}=this.classifyZoneIds(s);if(this.initDebugPanel(googletag,r.concat(n)),r.forEach(e=>(0,i.cf)(e)),n.forEach(i.wo),0!==r.length){e.cM("Eligible ids:",r),this.opt.abd&&this.appendAdblockDetector();var l=googletag.pubads().getSlots().filter(e=>s.indexOf(e.getSlotElementId())>=0);googletag.destroySlots(l),this.opt.sf&&(googletag.pubads().setForceSafeFrame(!0),googletag.pubads().setSafeFrameConfig({allowOverlayExpansion:!0,allowPushExpansion:!0,sandbox:!0})),e.cM("Targeting consent: Checking..."),void 0!==this.opt.targeting_consent&&(e.cM("Targeting consent: Parameter set"),e.cM("Targeting consent: Consent given? ",this.opt.targeting_consent),googletag.pubads().setRequestNonPersonalizedAds(this.opt.targeting_consent?0:1),this.opt.targeting_consent||googletag.pubads().setPrivacySettings({limitedAds:!0})),this.opt.ll||googletag.pubads().enableSingleRequest(),cam.sreEvent||(googletag.pubads().addEventListener("slotRenderEnded",e=>this.onSlotRendered(e)),cam.sreEvent=!0),this.setTargeting(googletag);var d=r.filter(e=>!this.opt.ll||o.indexOf(e.id)<0),c=r.filter(e=>!!this.opt.ll&&o.indexOf(e.id)>=0);e.cM("Up front ids:",d),e.cM("Lazy loaded ids:",c),d.forEach(t=>{e.cM(`Defining ad for element ${t.id}`),this.defineSlot(t.id,googletag),t.setAttribute("data-dfp-zone","true")}),googletag.enableServices(),d.forEach(t=>{e.cM(`Displaying ad for element ${t.id}`),googletag.cmd.push(()=>googletag.display(t.id))}),this.opt.ll&&(e.cM("Enabling lazy loading for GAM"),googletag.pubads().enableLazyLoad({fetchMarginPercent:0,renderMarginPercent:0}),e.cM("Setting up lazy loaded ad units"),c.forEach(t=>{e.cM(`Lazy loading - Defining Slot ${t.id}`),this.defineSlot(t.id,googletag)}),c.forEach(t=>{e.cM(`Lazy loading - Displaying ad for element ${t.id}`),googletag.cmd.push(()=>googletag.display(t.id))}))}else e.cM("Found no ad ids on page")}setTargeting(t){let s=this.opt.targeting;"SystemDefault"===s.ProductVariant&&(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?s.ProductVariant="Dark":s.ProductVariant="Light"),Object.keys(s).forEach(a=>{e.cM(`-> targeting - ${a}: ${s[a]}`),t.pubads().setTargeting(a,s[a])})}appendAdblockDetector(){const e=document.createElement("div");e.className="adsbox",e.id="clc-abd",e.style.position="absolute",e.style.pointerEvents="none",e.innerHTML=" ",document.body.appendChild(e)}onSlotRendered(s){try{const r=s.slot.getSlotElementId();let n=[];r||n.push("id=0");const l=document.getElementById(r);if(r&&!l&&n.push("el=0"),0!==n.length)return void this.stalled(n.join("&"));const{path:d,sizes:c,zone:p}=(0,a.Z7)(r);if(this.collapsed[p]&&s.isEmpty)return e.cM(`No line item for the element #${l.id}... collapsing.`),void(0,i.wo)(l);if(this.slotsRenderedEvents.push(s),s.lineItemId||s.creativeId||!s.isEmpty){e.cM(`Rendered ad for element #${l.id} [line item #${s.lineItemId}]`),e.cM(s);var o=l.parentElement;if(o.classList.contains("js-zone-container")){switch((0,i.cf)(o),r){case"dfp-tlb":this.opt.tlb_position===t.Above?o.classList.add("mb8"):o.classList.add("mt16");break;case"dfp-tag":o.classList.add("mb8");break;case"dfp-msb":o.classList.add("mt16");break;case"dfp-mlb":case"dfp-smlb":case"dfp-bmlb":o.classList.add("my8");break;case"dfp-isb":o.classList.add("mt24");break;case"dfp-m-aq":o.classList.add("my12"),o.classList.add("mx-auto")}(0,i.$Z)(o),(0,i.$Z)(l)}else e.cM(`No ad for element #${l.id}, collapsing`),e.cM(s),(0,i.wo)(l)}}catch(e){this.stalled("e=1")}}stalled(e){(new Image).src=`https://${this.clc_options.h}/stalled.gif?${e}`}defineSlot(t,s){"dfp-isb"===t&&(e.cM("-> targeting - Sidebar: Inline"),s.pubads().setTargeting("Sidebar",["Inline"])),"dfp-tsb"===t&&(e.cM("-> targeting - Sidebar: Right"),s.pubads().setTargeting("Sidebar",["Right"]));const{path:i,sizes:o,zone:r}=(0,a.Z7)(t);e.cM(`Defining slot for ${t}: ${i}, sizes: ${JSON.stringify(o)}`),s.defineSlot(i,o,t).addService(s.pubads())}importGptLibrary(){this.gptImported||(this.gptImported=!0,void 0===this.opt.targeting_consent||this.opt.targeting_consent?(0,i.Gx)("https://securepubads.g.doubleclick.net/tag/js/gpt.js"):(0,i.Gx)("https://pagead2.googlesyndication.com/tag/js/gpt.js"))}isGptReady(){return"undefined"!=typeof googletag&&!!googletag.apiReady}initGpt(){this.isGptReady()||(window.googletag={cmd:(0,i.QZ)(()=>this.importGptLibrary())})}initDebugPanel(t,s){e.cM("initDebugPanel"),e.cM("Not showing debug panel")}}})()})();
|
||
]]>
|
||
</script>
|
||
<script type="text/javascript">
|
||
//<![CDATA[
|
||
|
||
var cam = cam || {};
|
||
if (typeof cam.opt === 'undefined') {
|
||
cam.opt = {};
|
||
}
|
||
var opt = cam.opt;
|
||
|
||
opt.omni = 'BKjjS_f_zdoIAAAAAFeJAwACAAAAAgAAAAAALgAAAHxweXRob258cHl0aG9uLTMueHxnZW5lcmF0b3J8cHl0aG9uLTIueHx5aWVsZHwAa9v8RJmz5F12IA';
|
||
|
||
opt.sf = !0;
|
||
opt.hb = !1;
|
||
opt.ll = !0;
|
||
opt.tlb_position = 0;
|
||
opt.targeting_consent = !1;
|
||
opt.performance_consent = !1;
|
||
|
||
opt.targeting = {Registered:['false'],'so-tag':['python','python-3.x','generator','python-2.x','yield'],'tag-reportable':['python','python-3.x','generator','python-2.x','yield'],'tag-non-reportable':['python','python-3.x','generator','python-2.x','yield'],NumberOfAnswers:['20-plus']};
|
||
opt.adReportEnabled = !0;
|
||
opt.adReportUrl = '/ads/report-ad';
|
||
opt.adReportText = 'Report this ad';
|
||
opt.adReportFileTypeErrorMessage = 'Please select a PNG or JPG file.';
|
||
opt.adReportFileSizeErrorMessage = 'The file must be under 2 MiB.';
|
||
opt.adReportErrorText = 'Error uploading ad report.';
|
||
opt.adReportThanksText = 'Thanks for your feedback. We’ll review this against our code of conduct and take action if necessary.';
|
||
opt.adReportLoginExpiredMessage = 'Your login session has expired, please login and try again.';
|
||
opt.adReportLoginErrorMessage = 'An error occurred when loading the report form - please try again';
|
||
opt.adReportModalClass = 'js-ad-report';
|
||
|
||
|
||
opt.targeting.TargetingConsent = ['False_Passive'];
|
||
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
if (urlParams.has('dfptestads')) {
|
||
const dfptestads = urlParams.get('dfptestads');
|
||
opt.targeting.DfpTestAds = dfptestads;
|
||
}
|
||
|
||
var googletag = googletag || {};
|
||
googletag.cmd = googletag.cmd || [];
|
||
googletag.cmd.push(function () { cam.load(); });
|
||
//]]>
|
||
</script>
|
||
<script src="https://pagead2.googlesyndication.com/tag/js/gpt.js"></script>
|
||
<footer id="footer" class="site-footer js-footer" role="contentinfo">
|
||
<div class="site-footer--container">
|
||
<div class="site-footer--logo">
|
||
<a href="https://stackoverflow.com" aria-label="Stack Overflow"><svg aria-hidden="true" class="native svg-icon iconLogoGlyphMd" width="32" height="37" viewbox="0 0 32 37">
|
||
<path d="M26 33v-9h4v13H0V24h4v9h22Z" fill="#BCBBBB"></path>
|
||
<path d="m21.5 0-2.7 2 9.9 13.3 2.7-2L21.5 0ZM26 18.4 13.3 7.8l2.1-2.5 12.7 10.6-2.1 2.5ZM9.1 15.2l15 7 1.4-3-15-7-1.4 3Zm14 10.79.68-2.95-16.1-3.35L7 23l16.1 2.99ZM23 30H7v-3h16v3Z" fill="#F48024"></path></svg></a>
|
||
</div>
|
||
<nav class="site-footer--nav">
|
||
<div class="site-footer--col">
|
||
<h5 class="-title">
|
||
<a href="https://stackoverflow.com" class="js-gps-track" data-gps-track="footer.click({ location: 2, link: 15})">Stack Overflow</a>
|
||
</h5>
|
||
<ul class="-list js-primary-footer-links">
|
||
<li>
|
||
<a href="/questions" class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 16})">Questions</a>
|
||
</li>
|
||
<li>
|
||
<a href="/help" class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 3 })">Help</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="site-footer--col">
|
||
<h5 class="-title">
|
||
<a href="https://stackoverflow.co/" class="js-gps-track" data-gps-track="footer.click({ location: 2, link: 19 })">Products</a>
|
||
</h5>
|
||
<ul class="-list">
|
||
<li>
|
||
<a href="https://stackoverflow.co/teams" class="js-gps-track -link" data-ga="["teams traffic","footer - site nav","stackoverflow.com/teams",null,{"dimension4":"teams"}]" data-gps-track="footer.click({ location: 2, link: 29 })">Teams</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackoverflow.co/advertising" class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 21 })">Advertising</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackoverflow.co/collectives" class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 40 })">Collectives</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackoverflow.co/talent" class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 20 })">Talent</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="site-footer--col">
|
||
<h5 class="-title">
|
||
<a class="js-gps-track" data-gps-track="footer.click({ location: 2, link: 1 })" href="https://stackoverflow.co/">Company</a>
|
||
</h5>
|
||
<ul class="-list">
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 1 })" href="https://stackoverflow.co/">About</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 27 })" href="https://stackoverflow.co/company/press">Press</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 9 })" href="https://stackoverflow.co/company/work-here">Work Here</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 7 })" href="https://stackoverflow.com/legal">Legal</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 8 })" href="https://stackoverflow.com/legal/privacy-policy">Privacy Policy</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 37 })" href="https://stackoverflow.com/legal/terms-of-service">Terms of Service</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 13 })" href="https://stackoverflow.co/company/contact">Contact Us</a>
|
||
</li>
|
||
<li class="" id="consent-footer-link">
|
||
<a class="js-gps-track -link js-cookie-settings" data-gps-track="footer.click({ location: 2, link: 38 })" href="#" data-consent-popup-loader="footer">Cookie Settings</a>
|
||
</li>
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link: 39 })" href="https://stackoverflow.com/legal/cookie-policy">Cookie Policy</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="site-footer--col site-footer--categories-nav">
|
||
<div>
|
||
<h5 class="-title">
|
||
<a href="https://stackexchange.com" data-gps-track="footer.click({ location: 2, link: 30 })">Stack Exchange Network</a>
|
||
</h5>
|
||
<ul class="-list">
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#technology" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Technology</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#culturerecreation" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Culture & recreation</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#lifearts" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Life & arts</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#science" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Science</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#professional" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Professional</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://stackexchange.com/sites#business" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Business</a>
|
||
</li>
|
||
<li class="mt16 md:mt0">
|
||
<a href="https://api.stackexchange.com/" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">API</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://data.stackexchange.com/" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 24 })">Data</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<div class="site-footer--copyright fs-fine md:mt24">
|
||
<ul class="-list -social md:mb8">
|
||
<li>
|
||
<a class="js-gps-track -link" data-gps-track="footer.click({ location: 2, link:4 })" href="https://stackoverflow.blog?blb=1">Blog</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://www.facebook.com/officialstackoverflow/" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 31 })">Facebook</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://twitter.com/stackoverflow" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 32 })">Twitter</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://linkedin.com/company/stack-overflow" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 33 })">LinkedIn</a>
|
||
</li>
|
||
<li>
|
||
<a href="https://www.instagram.com/thestackoverflow" class="-link js-gps-track" data-gps-track="footer.click({ location: 2, link: 36 })">Instagram</a>
|
||
</li>
|
||
</ul>
|
||
<p class="md:mb0">
|
||
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under <span class="td-underline"><a href="https://stackoverflow.com/help/licensing">CC BY-SA</a></span>. <span id="svnrev">rev 2022.11.22.43050</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</footer><!-- Google tag (gtag.js) -->
|
||
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=G-WCZ03SZFCQ"></script>
|
||
<script>
|
||
<![CDATA[
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() { dataLayer.push(arguments); }
|
||
]]>
|
||
</script>
|
||
<script>
|
||
<![CDATA[
|
||
|
||
StackExchange.ready(function() {
|
||
|
||
var ga3Settings = {
|
||
autoLink: ["stackoverflow.blog","info.stackoverflowsolutions.com","stackoverflowsolutions.com"],
|
||
sendTitles: true,
|
||
tracker: window.ga,
|
||
trackingCodes: [
|
||
'UA-108242619-1'
|
||
],
|
||
checkDimension: 'dimension42'
|
||
};
|
||
|
||
var customGA4Dimensions = {};
|
||
|
||
|
||
var ga4Settings = {
|
||
tracker: gtag,
|
||
trackingCodes: [
|
||
'G-WCZ03SZFCQ'
|
||
],
|
||
consentsToPerformanceCookies: "denied",
|
||
consentsToTargetingCookies: "denied",
|
||
eventParameters: customGA4Dimensions,
|
||
checkForAdBlock: true
|
||
};
|
||
|
||
StackExchange.ga.init({ GA3: ga3Settings, GA4: ga4Settings });
|
||
|
||
|
||
StackExchange.ga.setDimension('dimension2', '|python|python-3.x|generator|python-2.x|yield|');
|
||
|
||
|
||
StackExchange.ga.setDimension('dimension3', 'Questions/Show');
|
||
|
||
|
||
StackExchange.ga.setDimension('dimension7', "1669282847.1554858645");
|
||
|
||
StackExchange.ga.trackPageView();
|
||
});
|
||
]]>
|
||
</script><iframe src="https://604bb4c29c9f3f7fec06f24a7d8a8cbb.safeframe.googlesyndication.com/safeframe/1-0-40/html/container.html" style="visibility: hidden; display: none;"></iframe>
|
||
<div class="ff-sans ps-fixed z-nav-fixed ws4 sm:w-auto p32 sm:p16 bg-black-750 fc-white bar-lg b16 l16 r16 js-consent-banner">
|
||
<svg aria-hidden="true" class="mln4 mb24 sm:d-none svg-spot spotCookieLg" style="color: var(--theme-button-filled-background-color)" width="96" height="96" viewbox="0 0 96 96">
|
||
<path d="M35 45.5a7.5 7.5 0 11-15 0 7.5 7.5 0 0115 0zM63.5 63a7.5 7.5 0 100-15 7.5 7.5 0 000 15zm-19 19a7.5 7.5 0 100-15 7.5 7.5 0 000 15z" opacity=".2"></path>
|
||
<path d="M56.99 2.53a23.1 23.1 0 0114.66 6.15h.01l.01.02c.57.55.61 1.27.5 1.74v.07a10.95 10.95 0 01-3.07 4.77 9 9 0 01-6.9 2.5 10.34 10.34 0 01-9.72-10.44v-.08a10 10 0 011.03-3.74l.01-.03.02-.02c.28-.5.82-.92 1.52-.95.63-.02 1.27-.02 1.93.01zm12.04 7.83a20.1 20.1 0 00-12.2-4.83l-.92-.03c-.23.6-.38 1.25-.43 1.94a7.34 7.34 0 006.95 7.34 6 6 0 004.64-1.7c.94-.88 1.6-1.9 1.96-2.72zm15.3 8.76a6.84 6.84 0 00-5.09-.24 7.9 7.9 0 00-3.28 2.05 1.8 1.8 0 00-.3 1.95l.02.02v.02a15.16 15.16 0 008.74 7.47c.64.23 1.32.08 1.8-.33a6.63 6.63 0 001.63-1.97l.01-.03.01-.03c1.67-3.5-.12-7.32-3.54-8.91zm-5.5 3.28c.36-.25.82-.5 1.35-.67.92-.3 1.92-.35 2.89.1 2.14 1 2.92 3.14 2.11 4.88-.12.21-.26.41-.43.6l-.26-.1a12.29 12.29 0 01-5.66-4.81zM32 24a2 2 0 11-4 0 2 2 0 014 0zm12 21a2 2 0 11-4 0 2 2 0 014 0zm36 4a2 2 0 11-4 0 2 2 0 014 0zm-7 21a2 2 0 11-4 0 2 2 0 014 0zM59 81a2 2 0 11-4 0 2 2 0 014 0zM22 63a2 2 0 11-4 0 2 2 0 014 0zm27 7a9 9 0 11-18 0 9 9 0 0118 0zm-3 0a6 6 0 10-12 0 6 6 0 0012 0zM33 41a9 9 0 11-18 0 9 9 0 0118 0zm-15 0a6 6 0 1012 0 6 6 0 00-12 0zm50 11a9 9 0 11-18 0 9 9 0 0118 0zm-3 0a6 6 0 10-12 0 6 6 0 0012 0zM44.08 4.24c.31.48.33 1.09.05 1.58a17.46 17.46 0 00-2.36 8.8c0 9.55 7.58 17.24 16.85 17.24 2.97 0 5.75-.78 8.16-2.15a1.5 1.5 0 012.1.66 12.08 12.08 0 0011 6.74 12.4 12.4 0 007.85-2.75 1.5 1.5 0 012.38.74A45.76 45.76 0 0192 48.16c0 24.77-19.67 44.9-44 44.9S4 72.93 4 48.16C4 25.23 20.84 6.28 42.64 3.58a1.5 1.5 0 011.44.66zM40.22 7C21.32 10.71 7 27.7 7 48.16c0 23.17 18.39 41.9 41 41.9s41-18.73 41-41.9c0-3.52-.42-6.93-1.22-10.2a15.5 15.5 0 01-7.9 2.15c-5.5 0-10.36-2.83-12.97-7.1a19.46 19.46 0 01-8.28 1.85c-11 0-19.86-9.1-19.86-20.24 0-2.7.52-5.26 1.45-7.62zM92 91a2 2 0 100-4 2 2 0 000 4zM7 8.5a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0zM82.5 90a1.5 1.5 0 100-3 1.5 1.5 0 000 3zm9.5-7.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM13.5 8a1.5 1.5 0 100-3 1.5 1.5 0 000 3zM80 14.5a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM53.5 20a1.5 1.5 0 100-3 1.5 1.5 0 000 3z"></path></svg>
|
||
<p class="fs-body2 fw-bold mb4">
|
||
Your privacy
|
||
</p>
|
||
<p class="mb16 s-anchors s-anchors__inherit s-anchors__underlined">
|
||
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our <a href="https://stackoverflow.com/legal/cookie-policy">Cookie Policy</a>.
|
||
</p>
|
||
<div class="d-flex gs8 ai-stretch fd-column sm:fd-row">
|
||
<button class="flex--item s-btn s-btn__primary js-accept-cookies js-consent-banner-hide">Accept all cookies</button> <button class="flex--item s-btn s-btn__filled js-cookie-settings" data-consent-popup-loader="banner">Customize settings</button>
|
||
</div>
|
||
</div>
|
||
<div id="onetrust-consent-sdk" class="d-none"></div>
|
||
<div id="onetrust-banner-sdk" data-controller="s-modal"></div>
|
||
<div id="ot-pc-content" class="d-none"></div>
|
||
<div id="onetrust-style" class="d-none">
|
||
 
|
||
</div>
|
||
<div class="d-none js-consent-banner-version" data-consent-banner-version="baseline"></div>
|
||
</body>
|
||
</html>
|