<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Default arguments in Python: two easy blunders</title>
	<atom:link href="http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/</link>
	<description>Just another WordPress weblog</description>
	<pubDate>Fri, 04 Jul 2008 14:58:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: garth</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5600</link>
		<dc:creator>garth</dc:creator>
		<pubDate>Thu, 12 Jun 2008 05:51:46 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5600</guid>
		<description>I put the open() with the rest of the code that does the work; I find it easier to read. Great use of an "and" in that last line, too.</description>
		<content:encoded><![CDATA[<p>I put the open() with the rest of the code that does the work; I find it easier to read. Great use of an &#8220;and&#8221; in that last line, too.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: swr</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5526</link>
		<dc:creator>swr</dc:creator>
		<pubDate>Sun, 01 Jun 2008 20:50:30 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5526</guid>
		<description>Jay said,
ON MAY 9TH, 2008 AT 12:57 PM

file = None

try:
file = open(’/tmp/somefile’)
finally:
file and file.close()

why putting 'open' into the try-finally block?
If it fails there is nothing to close anyway.
I was repeating such construction many times until I realized it's a bit illogical.</description>
		<content:encoded><![CDATA[<p>Jay said,<br />
ON MAY 9TH, 2008 AT 12:57 PM</p>
<p>file = None</p>
<p>try:<br />
file = open(’/tmp/somefile’)<br />
finally:<br />
file and file.close()</p>
<p>why putting &#8216;open&#8217; into the try-finally block?<br />
If it fails there is nothing to close anyway.<br />
I was repeating such construction many times until I realized it&#8217;s a bit illogical.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: garth</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5419</link>
		<dc:creator>garth</dc:creator>
		<pubDate>Thu, 15 May 2008 01:24:32 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5419</guid>
		<description>I just batch-approved all these excellent comments. Thanks in particular for all the reminders to use the 'or' operator. Cheers!</description>
		<content:encoded><![CDATA[<p>I just batch-approved all these excellent comments. Thanks in particular for all the reminders to use the &#8216;or&#8217; operator. Cheers!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jasko</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5408</link>
		<dc:creator>Jasko</dc:creator>
		<pubDate>Mon, 12 May 2008 17:26:50 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5408</guid>
		<description>How about something like this to handle both cases?

def report(when=time.time):
... 	if hasattr(when, "__call__"):
... 		print when()
... 	else:
... 		print when

&#62;&#62;&#62; report()
1210613185.87
&#62;&#62;&#62; report("Now")
Now

Though regarding your second example --- yowza! I can see a sleepless night worrying about that one!</description>
		<content:encoded><![CDATA[<p>How about something like this to handle both cases?</p>
<p>def report(when=time.time):<br />
&#8230; 	if hasattr(when, &#8220;__call__&#8221;):<br />
&#8230; 		print when()<br />
&#8230; 	else:<br />
&#8230; 		print when</p>
<p>&gt;&gt;&gt; report()<br />
1210613185.87<br />
&gt;&gt;&gt; report(&#8221;Now&#8221;)<br />
Now</p>
<p>Though regarding your second example &#8212; yowza! I can see a sleepless night worrying about that one!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: me</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5399</link>
		<dc:creator>me</dc:creator>
		<pubDate>Sun, 11 May 2008 10:58:18 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5399</guid>
		<description>the report example would be simpler with

def report(when=None):
    when = when or time.time()
    print when</description>
		<content:encoded><![CDATA[<p>the report example would be simpler with</p>
<p>def report(when=None):<br />
    when = when or time.time()<br />
    print when</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5391</link>
		<dc:creator>David</dc:creator>
		<pubDate>Sat, 10 May 2008 13:06:33 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5391</guid>
		<description>For the report function, I would use this implementation :
&#62;&#62;&#62; def report(when=time.time):
…     print when()

Note that no parenthesis are used in the default parameter.</description>
		<content:encoded><![CDATA[<p>For the report function, I would use this implementation :<br />
&gt;&gt;&gt; def report(when=time.time):<br />
…     print when()</p>
<p>Note that no parenthesis are used in the default parameter.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: saluk</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5388</link>
		<dc:creator>saluk</dc:creator>
		<pubDate>Sat, 10 May 2008 02:14:06 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5388</guid>
		<description>Alternately, this (mis?)feature can be used to your advantage in certain situations:

def load_file(filename,cache={}):
   if filename not in cache:
      cache[filename] = open(filename)
   return cache[filename]

Still, this does cause more bugs than I would like.  Knowing a little bit of how python works I can't think of a different way to do this to keep this from happening.  Another idiom perhaps is this:

def getval(f):
	if callable(f):
		return f()
	return f
def report(when=time.time):
	print getval(when)

The only case where this doesn't work of course, is if the arg is meant to hold a function and not a value, but this is rare (and doesn't suffer from the default problem).  I like this better than having a bunch of None default values in my constructors.

I tried to think of a decorator solution, but it seems like you will still have the early execution thing, and what we are after is lazy execution.  But it can't happen every time, because you do want to be able to set a default value based on the output of a function in some situations.

Do we need a function that evaluates to itself the first time, and then generates values after that?  Maybe a generator solution?

Mutables are an even harder issue though, and I think that is a much more common bug as well than the functional one.  I wouldn't mind warnings for assigning mutables to default arguments.</description>
		<content:encoded><![CDATA[<p>Alternately, this (mis?)feature can be used to your advantage in certain situations:</p>
<p>def load_file(filename,cache={}):<br />
   if filename not in cache:<br />
      cache[filename] = open(filename)<br />
   return cache[filename]</p>
<p>Still, this does cause more bugs than I would like.  Knowing a little bit of how python works I can&#8217;t think of a different way to do this to keep this from happening.  Another idiom perhaps is this:</p>
<p>def getval(f):<br />
	if callable(f):<br />
		return f()<br />
	return f<br />
def report(when=time.time):<br />
	print getval(when)</p>
<p>The only case where this doesn&#8217;t work of course, is if the arg is meant to hold a function and not a value, but this is rare (and doesn&#8217;t suffer from the default problem).  I like this better than having a bunch of None default values in my constructors.</p>
<p>I tried to think of a decorator solution, but it seems like you will still have the early execution thing, and what we are after is lazy execution.  But it can&#8217;t happen every time, because you do want to be able to set a default value based on the output of a function in some situations.</p>
<p>Do we need a function that evaluates to itself the first time, and then generates values after that?  Maybe a generator solution?</p>
<p>Mutables are an even harder issue though, and I think that is a much more common bug as well than the functional one.  I wouldn&#8217;t mind warnings for assigning mutables to default arguments.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Fredrik</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5386</link>
		<dc:creator>Fredrik</dc:creator>
		<pubDate>Fri, 09 May 2008 15:20:05 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5386</guid>
		<description>Patrick's example has nothing to do with Python's default argument handling, though.  His mistake was thinking that if you write

    x = expression

and then evaluate "x" some time in the future, Python would by some reason evaluate the expression again.  I'm sure he knows that things doesn't work this way, and that it was just the unusual context (defining models by setting class attributes) that was confusing him.</description>
		<content:encoded><![CDATA[<p>Patrick&#8217;s example has nothing to do with Python&#8217;s default argument handling, though.  His mistake was thinking that if you write</p>
<p>    x = expression</p>
<p>and then evaluate &#8220;x&#8221; some time in the future, Python would by some reason evaluate the expression again.  I&#8217;m sure he knows that things doesn&#8217;t work this way, and that it was just the unusual context (defining models by setting class attributes) that was confusing him.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Nick</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5385</link>
		<dc:creator>Nick</dc:creator>
		<pubDate>Fri, 09 May 2008 14:55:30 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5385</guid>
		<description>Just watch this useful video, you'll learn a lot of python concepts.
Understanding Python
http://video.google.com/videoplay?docid=7760178035196894549&#38;q=python&#38;ei=eGUkSLqADpeG2wL1lZyfDA</description>
		<content:encoded><![CDATA[<p>Just watch this useful video, you&#8217;ll learn a lot of python concepts.<br />
Understanding Python<br />
<a href="http://video.google.com/videoplay?docid=7760178035196894549&amp;q=python&amp;ei=eGUkSLqADpeG2wL1lZyfDA" rel="nofollow">http://video.google.com/videoplay?docid=7760178035196894549&amp;q=python&amp;ei=eGUkSLqADpeG2wL1lZyfDA</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tom</title>
		<link>http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/#comment-5383</link>
		<dc:creator>Tom</dc:creator>
		<pubDate>Fri, 09 May 2008 11:43:37 +0000</pubDate>
		<guid isPermaLink="false">http://www.deadlybloodyserious.com/?p=2055#comment-5383</guid>
		<description>I was hit by number 2 a few days ago on a project, took me a long time to figure out what was going on.</description>
		<content:encoded><![CDATA[<p>I was hit by number 2 a few days ago on a project, took me a long time to figure out what was going on.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
