added section on optional and named arguments to your-first-python-program

This commit is contained in:
Mark Pilgrim
2009-05-15 15:32:10 -04:00
parent 3b8474a7bf
commit 8a88425901
+45
View File
@@ -75,6 +75,51 @@ if __name__ == "__main__":
<p><span>&#x261E;</span>In Java and other statically-typed languages, you must specify the datatype of the function return value and each function argument. In Python, you never explicitly specify the datatype of anything. Based on what value you assign, Python keeps track of the datatype internally.
</blockquote>
<h3 id=optional-arguments>Optional and Named Arguments</h3>
<p>Python allows function arguments to have default values; if the function is called without the argument, the argument gets its default value. Futhermore, arguments can be specified in any order by using named arguments.
<p>Let&#8217;s take another look at that <code>approximate_size</code> function declaration:
<pre><code>def approximate_size(size, a_kilobyte_is_1024_bytes=True):</code></pre>
<p>The second argument, <var>a_kilobyte_is_1024_bytes</var>, specifies a default value of <code>True</code>. This means the argument is <i>optional</i>; you can call the function without it, and Python will act as if you had called it with <code>True</code> as a second parameter.
<p>Now look at the bottom of the script:
<pre><code>
if __name__ == "__main__":
<a> print(approximate_size(1000000000000, False)) <span>&#x2460;</span></a>
<a> print(approximate_size(1000000000000)) <span>&#x2461;</span></a></code></pre>
<ol>
<li>This calls the <code>approximate_size()</code> function with two argument. Within the <code>approximate_size()</code> function, <var>a_kilobyte_is_1024_bytes</var> will be <code>False</code>, since you explicitly passed <code>False</code> as the second argument.
<li>This calls the <code>approximate_size()</code> function with only one argument. But that&#8217;s OK, because the second argument is optional! Since the caller doesn&#8217;t specify, the second argument defaults to <code>True</code>, as defined by the function declaration.
</ol>
<p>You can also pass values into a function by name.
<pre class=screen>
<samp class=p>>>> </samp><kbd>from humansize import approximate_size</kbd>
<a><samp class=p>>>> </samp><kbd>approximate_size(4000, a_kilobyte_is_1024_bytes=False)</kbd> <span>&#x2460;</span></a>
<samp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd>approximate_size(size=4000, a_kilobyte_is_1024_bytes=False)</kbd> <span>&#x2461;</span></a>
<samp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd>approximate_size(a_kilobyte_is_1024_bytes=False, size=4000)</kbd> <span>&#x2462;</span></a>
<samp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd>approximate_size(a_kilobyte_is_1024_bytes=False, 4000)</kbd> <span>&#x2463;</span></a>
<samp class=traceback> File "&lt;stdin>", line 1
SyntaxError: non-keyword arg after keyword arg</samp>
<a><samp class=p>>>> </samp><kbd>approximate_size(size=4000, False)</kbd> <span>&#x2464;</span></a>
<samp class=traceback> File "&lt;stdin>", line 1
SyntaxError: non-keyword arg after keyword arg</samp></pre>
<ol>
<li>This calls the <code>approximate_size()</code> function with <code>4000</code> for the first argument (<var>size</var>) and <code>False</code> for the argument named <var>a_kilobyte_is_1024_bytes</var>. (That happens to be the second argument, but doesn&#8217;t matter, as you&#8217;ll see in a minute.)
<li>This calls the <code>approximate_size()</code> function with <code>4000</code> for the argument named <var>size</var> and <code>False</code> for the argument named <var>a_kilobyte_is_1024_bytes</var>. (These named arguments happen to be in the same order as the arguments are listed in the function declaration, but that doesn&#8217;t matter either.)
<li>This calls the <code>approximate_size()</code> function with <code>False</code> for the argument named <var>a_kilobyte_is_1024_bytes</var> and <code>4000</code> for the argument named <var>size</var>. (See? I told you the order didn&#8217;t matter.)
<li>This call fails, because you have a named argument followed by an unnamed (positional) argument, and that never works. Reading the argument list from left to right, once you have a single named argument, the rest of the arguments must also be named.
<li>This call fails too, for the same reason as the previous call. Is that surprising? After all, you passed <code>4000</code> for the argument named <code>size</code>, then &#8220;obviously&#8221; that <code>False</code> value was meant for the <var>a_kilobyte_is_1024_bytes</var> argument. But Python doesn&#8217;t work that way. As soon as you have a named argument, all arguments to the right of that need to be named arguments, too.
</ol>
<h2 id=readability>Writing Readable Code</h2>
<p>I won&#8217;t bore you with a long finger-wagging speech about the importance of documenting your code. Just know that code is written once but read many times, and the most important audience for your code is yourself, six months after writing it (i.e. after you&#8217;ve forgotten everything but need to fix something). Python makes it easy to write readable code, so take advantage of it. You&#8217;ll thank me in six months.
<h3 id=docstrings>Documentation Strings</h3>