{"id":1157,"date":"2012-04-01T20:26:40","date_gmt":"2012-04-02T02:26:40","guid":{"rendered":"http:\/\/thesmithfam.org\/blog\/?p=1157"},"modified":"2019-08-12T07:15:07","modified_gmt":"2019-08-12T13:15:07","slug":"dangerous-python-default-arguments","status":"publish","type":"post","link":"https:\/\/thesmithfam.org\/blog\/2012\/04\/01\/dangerous-python-default-arguments\/","title":{"rendered":"Dangerous Python Default Arguments"},"content":{"rendered":"<style>\nspan.intro-crap a {\ntext-decoration: underline;\n}\n<\/style>\n<p>Dangerous? Really? Well, not if you understand how it works.<\/p>\n<p><span class=\"intro-crap\">Note: <a href=\"http:\/\/www.deadlybloodyserious.com\/2008\/05\/default-argument-blunders\/\">I&#8217;m<\/a> <a href=\"http:\/\/effbot.org\/zone\/default-values.htm\">not<\/a> <a href=\"http:\/\/www.network-theory.co.uk\/docs\/pytut\/DefaultArgumentValues.html\">the<\/a> <a href=\"http:\/\/stackoverflow.com\/questions\/1132941\/least-astonishment-in-python-the-mutable-default-argument\">first<\/a> to write about this subject.<\/span><\/p>\n<p>When writing a function in Python, it&#8217;s handy to use default argument values like this:<\/p>\n\n<p>And you <b>think<\/b> this will provide an easy way to let lazy callers pass no arguments to your function, and it will simply be called as if they had passed <tt>['some item']<\/tt>.<\/p>\n<p><b>But you would be wrong.<\/b><\/p>\n<p>What <b>actually<\/b> happens is this (interactive shell output):<\/p>\n\n<p>That&#8217;s right. Python creates a new object, named <tt>some_list<\/tt> that persists as an attribute of the function. If callers don&#8217;t pass their own <tt>some_list<\/tt> object, this one, the same one, is used each time your function is called.<\/p>\n<p>Weird, huh?<\/p>\n<p>If users pass their own <tt>some_list<\/tt> object, then sanity is restored:<\/p>\n\n<p>So why is this? Python stores each default argument value in a special attribute on the function called <tt>func_defaults<\/tt>. You can inspect any function&#8217;s default arguments like this:<\/p>\n\n<p>Because functions in Python are just objects, you can store arbitrary attributes on them. And indeed, you can actually <b>modify<\/b> the default function arguments at run time, like this:<\/p>\n<script src=\"https:\/\/gist.github.com\/2280054.js\"><\/script><noscript><pre><code class=\"language-text text\">&gt;&gt;&gt; do_something.func_defaults = ([42],)\n&gt;&gt;&gt; do_something()\n[42, &#039;some item&#039;]\n&gt;&gt;&gt; <\/code><\/pre><\/noscript>\n<p><b>But remember<\/b>: Just because you <b>can<\/b> doesn&#8217;t mean you <b>should<\/b>. I would not recommend making a habit of stuff like this, especially if you like <b>not<\/b> having your co-workers hate you.<\/p>\n<p>It&#8217;s always good to know how your tools work. Inside and out.<\/p>\n<p>I discovered this behavior when investigating the pylint <a href=\"http:\/\/pylint-messages.wikidot.com\/messages:w0102\">W0102 message<\/a>, and discovered that this message actually inspired an entire <a href=\"http:\/\/pylint-messages.wikidot.com\/\">wiki of Pylint message descriptions<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dangerous? Really? Well, not if you understand how it works. Note: I&#8217;m not the first to write about this subject. When writing a function in Python, it&#8217;s handy to use default argument values like this: And you think this will provide an easy way to let lazy callers pass no arguments to your function, and [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-1157","post","type-post","status-publish","format-standard","hentry","category-code-and-cruft"],"_links":{"self":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/comments?post=1157"}],"version-history":[{"count":33,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1157\/revisions"}],"predecessor-version":[{"id":1505,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/posts\/1157\/revisions\/1505"}],"wp:attachment":[{"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/media?parent=1157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/categories?post=1157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thesmithfam.org\/blog\/wp-json\/wp\/v2\/tags?post=1157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}