SEESenv/web/html/ch5func.html
changeset 42 1f61ee485958
parent 41 e54725be4df6
child 43 134b87b382f5
equal deleted inserted replaced
41:e54725be4df6 42:1f61ee485958
     1 <html>
       
     2 <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>Chapter. func</title><link rel="stylesheet" href="/review/support/styles.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.74.3" /><link rel="shortcut icon" type="image/png" href="/review/support/figs/favicon.png" /><script type="text/javascript" src="/review/support/jquery-min.js"></script><script type="text/javascript" src="/review/support/form.js"></script><script type="text/javascript" src="/review/support/hsbook.js"></script></head>
       
     3 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="chapter" id="ch5func">
       
     4 <div class="titlepage"></div>
       
     5 <div class="toc">
       
     6 <p><b>Table of Contents</b></p>
       
     7 <dl>
       
     8 <dt><span class="article"><a href="#id2803272">Functional Approach</a></span></dt>
       
     9 <dd><dl>
       
    10 <dt><span class="section"><a href="#id2854310">1. Function scope</a></span></dt>
       
    11 <dt><span class="section"><a href="#id2854368">2. Default Arguments</a></span></dt>
       
    12 <dt><span class="section"><a href="#id2854408">3. Keyword Arguments</a></span></dt>
       
    13 <dt><span class="section"><a href="#id2854524">4. Parameter Packing and Unpacking</a></span></dt>
       
    14 <dt><span class="section"><a href="#id2854624">5. Nested Functions and Scopes</a></span></dt>
       
    15 <dt><span class="section"><a href="#id2854673">6. map, reduce and filter functions</a></span></dt>
       
    16 <dd><dl><dt><span class="section"><a href="#id2854863">6.1. List Comprehensions</a></span></dt></dl></dd>
       
    17 </dl></dd>
       
    18 </dl>
       
    19 </div>
       
    20 <div class="article" title="Functional Approach">
       
    21 <div class="titlepage">
       
    22 <div><div><h2 class="title">
       
    23 <a name="id2803272"></a>Functional Approach</h2></div></div>
       
    24 <hr />
       
    25 </div>
       
    26 <div class="toc">
       
    27 <p><b>Table of Contents</b></p>
       
    28 <dl>
       
    29 <dt><span class="section"><a href="#id2854310">1. Function scope</a></span></dt>
       
    30 <dt><span class="section"><a href="#id2854368">2. Default Arguments</a></span></dt>
       
    31 <dt><span class="section"><a href="#id2854408">3. Keyword Arguments</a></span></dt>
       
    32 <dt><span class="section"><a href="#id2854524">4. Parameter Packing and Unpacking</a></span></dt>
       
    33 <dt><span class="section"><a href="#id2854624">5. Nested Functions and Scopes</a></span></dt>
       
    34 <dt><span class="section"><a href="#id2854673">6. map, reduce and filter functions</a></span></dt>
       
    35 <dd><dl><dt><span class="section"><a href="#id2854863">6.1. List Comprehensions</a></span></dt></dl></dd>
       
    36 </dl>
       
    37 </div>
       
    38 <p id="ch5func_1"><span class="emphasis"><em>Functions</em></span> allow us to enclose a set of statements and call the function again
       
    39 and again instead of repeating the group of statements everytime. Functions also
       
    40 allow us to isolate a piece of code from all the other code and provides the
       
    41 convenience of not polluting the global variables.</p>
       
    42 <p id="ch5func_2"><span class="emphasis"><em>Function</em></span> in python is defined with the keyword <span class="strong"><strong>def</strong></span> followed by the name
       
    43 of the function, in turn followed by a pair of parenthesis which encloses the
       
    44 list of parameters to the function. The definition line ends with a ':'. The
       
    45 definition line is followed by the body of the function intended by one block.
       
    46 The <span class="emphasis"><em>Function</em></span> must return a value:</p>
       
    47 <pre class="programlisting">
       
    48 def factorial(n):
       
    49   fact = 1
       
    50   for i in range(2, n):
       
    51     fact *= i
       
    52 
       
    53   return fact</pre>
       
    54 <p id="ch5func_3">The code snippet above defines a function with the name factorial, takes the
       
    55 number for which the factorial must be computed, computes the factorial and
       
    56 returns the value.</p>
       
    57 <p id="ch5func_4">A <span class="emphasis"><em>Function</em></span> once defined can be used or called anywhere else in the program. We
       
    58 call a fucntion with its name followed by a pair of parenthesis which encloses
       
    59 the arguments to the function.</p>
       
    60 <p id="ch5func_5">The value that function returns can be assigned to a variable. Let's call the
       
    61 above function and store the factorial in a variable:</p>
       
    62 <pre class="programlisting">
       
    63 fact5 = factorial(5)</pre>
       
    64 <p id="ch5func_6">The value of fact5 will now be 120, which is the factorial of 5. Note that we
       
    65 passed 5 as the argument to the function.</p>
       
    66 <p id="ch5func_7">It may be necessary to document what the function does, for each of the function
       
    67 to help the person who reads our code to understand it better. In order to do
       
    68 this Python allows the first line of the function body to be a string. This
       
    69 string is called as <span class="emphasis"><em>Documentation String</em></span> or <span class="emphasis"><em>docstring</em></span>. <span class="emphasis"><em>docstrings</em></span> prove
       
    70 to be very handy since there are number of tools which can pull out all the
       
    71 docstrings from Python functions and generate the documentation automatically
       
    72 from it. <span class="emphasis"><em>docstrings</em></span> for functions can be written as follows:</p>
       
    73 <pre class="programlisting">
       
    74 def factorial(n):
       
    75   'Returns the factorial for the number n.'
       
    76   fact = 1
       
    77   for i in range(2, n):
       
    78     fact *= i
       
    79 
       
    80   return fact</pre>
       
    81 <p id="ch5func_8">An important point to note at this point is that, a function can return any
       
    82 Python value or a Python object, which also includes a <span class="emphasis"><em>Tuple</em></span>. A <span class="emphasis"><em>Tuple</em></span> is
       
    83 just a collection of values and those values themselves can be of any other
       
    84 valid Python datatypes, including <span class="emphasis"><em>Lists</em></span>, <span class="emphasis"><em>Tuples</em></span>, <span class="emphasis"><em>Dictionaries</em></span> among other
       
    85 things. So effectively, if a function can return a tuple, it can return any
       
    86 number of values through a tuple</p>
       
    87 <p id="ch5func_9">Let us write a small function to swap two values:</p>
       
    88 <pre class="programlisting">
       
    89 def swap(a, b):
       
    90   return b, a
       
    91 
       
    92 c, d = swap(a, b)</pre>
       
    93 <div class="section" title="1.Function scope">
       
    94 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
    95 <a name="id2854310"></a>1.Function scope</h2></div></div></div>
       
    96 <p id="ch5func_a">The variables used inside the function are confined to the function's scope
       
    97 and doesn't pollute the variables of the same name outside the scope of the
       
    98 function. Also the arguments passed to the function are passed by-value if
       
    99 it is of basic Python data type:</p>
       
   100 <pre class="programlisting">
       
   101 def cant_change(n):
       
   102   n = 10
       
   103 
       
   104 n = 5
       
   105 cant_change(n)</pre>
       
   106 <p id="ch5func_b">Upon running this code, what do you think would have happened to value of n
       
   107 which was assigned 5 before the function call? If you have already tried out
       
   108 that snippet on the interpreter you already know that the value of n is not
       
   109 changed. This is true of any immutable types of Python like <span class="emphasis"><em>Numbers</em></span>, <span class="emphasis"><em>Strings</em></span>
       
   110 and <span class="emphasis"><em>Tuples</em></span>. But when you pass mutable objects like <span class="emphasis"><em>Lists</em></span> and <span class="emphasis"><em>Dictionaries</em></span>
       
   111 the values are manipulated even outside the function:</p>
       
   112 <pre class="programlisting">
       
   113 &gt;&gt;&gt; def can_change(n):
       
   114 ...   n[1] = James
       
   115 ...
       
   116 
       
   117 &gt;&gt;&gt; name = ['Mr.', 'Steve', 'Gosling']
       
   118 &gt;&gt;&gt; can_change(name)
       
   119 &gt;&gt;&gt; name
       
   120 ['Mr.', 'James', 'Gosling']</pre>
       
   121 <p id="ch5func_c">If nothing is returned by the function explicitly, Python takes care to return
       
   122 None when the funnction is called.</p>
       
   123 </div>
       
   124 <div class="section" title="2.Default Arguments">
       
   125 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   126 <a name="id2854368"></a>2.Default Arguments</h2></div></div></div>
       
   127 <p id="ch5func_d">There may be situations where we need to allow the functions to take the
       
   128 arguments optionally. Python allows us to define function this way by providing
       
   129 a facility called <span class="emphasis"><em>Default Arguments</em></span>. For example, we need to write a function
       
   130 that returns a list of fibonacci numbers. Since our function cannot generate an
       
   131 infinite list of fibonacci numbers, we need to specify the number of elements
       
   132 that the fibonacci sequence must contain. Suppose, additionally, we want to the
       
   133 function to return 10 numbers in the sequence if no option is specified we can
       
   134 define the function as follows:</p>
       
   135 <pre class="programlisting">
       
   136 def fib(n=10):
       
   137   fib_list = [0, 1]
       
   138   for i in range(n - 2):
       
   139     next = fib_list[-2] + fib_list[-1]
       
   140     fib_list.append(next)
       
   141   return fib_list</pre>
       
   142 <p id="ch5func_e">When we call this function, we can optionally specify the value for the
       
   143 parameter n, during the call as an argument. Calling with no argument and
       
   144 argument with n=5 returns the following fibonacci sequences:</p>
       
   145 <pre class="programlisting">
       
   146 fib()
       
   147 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
       
   148 fib(5)
       
   149 [0, 1, 1, 2, 3]</pre>
       
   150 </div>
       
   151 <div class="section" title="3.Keyword Arguments">
       
   152 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   153 <a name="id2854408"></a>3.Keyword Arguments</h2></div></div></div>
       
   154 <p id="ch5func_f">When a function takes a large number of arguments, it may be difficult to
       
   155 remember the order of the parameters in the function definition or it may
       
   156 be necessary to pass values to only certain parameters since others take
       
   157 the default value. In either of these cases, Python provides the facility
       
   158 of passing arguments by specifying the name of the parameter as defined in
       
   159 the function definition. This is known as <span class="emphasis"><em>Keyword Arguments</em></span>.</p>
       
   160 <p id="ch5func_10">In a function call, <span class="emphasis"><em>Keyword arguments</em></span> can be used for each argument, in the
       
   161 following fashion:</p>
       
   162 <pre class="programlisting">
       
   163 argument_name=argument_value
       
   164 Also denoted as: keyword=argument
       
   165 
       
   166 def wish(name='World', greetings='Hello'):
       
   167   print "%s, %s!" % (greetings, name)</pre>
       
   168 <p id="ch5func_11">This function can be called in one of the following ways. It is important to
       
   169 note that no restriction is imposed in the order in which <span class="emphasis"><em>Keyword arguments</em></span>
       
   170 can be specified. Also note, that we have combined <span class="emphasis"><em>Keyword arguments</em></span> with
       
   171 <span class="emphasis"><em>Default arguments</em></span> in this example, however it is not necessary:</p>
       
   172 <pre class="programlisting">
       
   173 wish(name='Guido', greetings='Hey')
       
   174 wish(greetings='Hey', name='Guido')</pre>
       
   175 <p id="ch5func_12">Calling functions by specifying arguments in the order of parameters specified
       
   176 in the function definition is called as <span class="emphasis"><em>Positional arguments</em></span>, as opposed to
       
   177 <span class="emphasis"><em>Keyword arguments</em></span>. It is possible to use both <span class="emphasis"><em>Positional arguments</em></span> and
       
   178 <span class="emphasis"><em>Keyword arguments</em></span> in a single function call. But Python doesn't allow us to
       
   179 bungle up both of them. The arguments to the function, in the call, must always
       
   180 start with <span class="emphasis"><em>Positional arguments</em></span> which is in turn followed by <span class="emphasis"><em>Keyword
       
   181 arguments</em></span>:</p>
       
   182 <pre class="programlisting">
       
   183 def my_func(x, y, z, u, v, w):
       
   184   # initialize variables.
       
   185   ...
       
   186   # do some stuff
       
   187   ...
       
   188   # return the value</pre>
       
   189 <p id="ch5func_13">It is valid to call the above functions in the following ways:</p>
       
   190 <pre class="programlisting">
       
   191 my_func(10, 20, 30, u=1.0, v=2.0, w=3.0)
       
   192 my_func(10, 20, 30, 1.0, 2.0, w=3.0)
       
   193 my_func(10, 20, z=30, u=1.0, v=2.0, w=3.0)
       
   194 my_func(x=10, y=20, z=30, u=1.0, v=2.0, w=3.0)</pre>
       
   195 <p id="ch5func_14">Following lists some of the invalid calls:</p>
       
   196 <pre class="programlisting">
       
   197 my_func(10, 20, z=30, 1.0, 2.0, 3.0)
       
   198 my_func(x=10, 20, z=30, 1.0, 2.0, 3.0)
       
   199 my_func(x=10, y=20, z=30, u=1.0, v=2.0, 3.0)</pre>
       
   200 </div>
       
   201 <div class="section" title="4.Parameter Packing and Unpacking">
       
   202 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   203 <a name="id2854524"></a>4.Parameter Packing and Unpacking</h2></div></div></div>
       
   204 <p id="ch5func_15">The positional arguments passed to a function can be collected in a tuple
       
   205 parameter and keyword arguments can be collected in a dictionary. Since keyword
       
   206 arguments must always be the last set of arguments passed to a function, the
       
   207 keyword dictionary parameter must be the last parameter. The function definition
       
   208 must include a list explicit parameters, followed by tuple paramter collecting
       
   209 parameter, whose name is preceded by a <span class="strong"><strong>*</strong></span>, for collecting positional
       
   210 parameters, in turn followed by the dictionary collecting parameter, whose name
       
   211 is preceded by a <span class="strong"><strong>**</strong></span></p>
       
   212 <pre class="programlisting">
       
   213 def print_report(title, *args, **name):
       
   214   """Structure of *args*
       
   215   (age, email-id)
       
   216   Structure of *name*
       
   217   {
       
   218       'first': First Name
       
   219       'middle': Middle Name
       
   220       'last': Last Name
       
   221   }
       
   222   """
       
   223 
       
   224   print "Title: %s" % (title)
       
   225   print "Full name: %(first)s %(middle)s %(last)s" % name
       
   226   print "Age: %d nEmail-ID: %s" % args</pre>
       
   227 <p id="ch5func_16">The above function can be called as. Note, the order of keyword parameters can
       
   228 be interchanged:</p>
       
   229 <pre class="programlisting">
       
   230 &gt;&gt;&gt; print_report('Employee Report', 29, 'johny@example.com', first='Johny',
       
   231                  last='Charles', middle='Douglas')
       
   232 Title: Employee Report
       
   233 Full name: Johny Douglas Charles
       
   234 Age: 29
       
   235 Email-ID: johny@example.com</pre>
       
   236 <p id="ch5func_17">The reverse of this can also be achieved by using a very identical syntax while
       
   237 calling the function. A tuple or a dictionary can be passed as arguments in
       
   238 place of a list of <span class="emphasis"><em>Positional arguments</em></span> or <span class="emphasis"><em>Keyword arguments</em></span> respectively
       
   239 using <span class="strong"><strong>*</strong></span> or <span class="strong"><strong>**</strong></span></p>
       
   240 <pre class="programlisting">
       
   241 def print_report(title, age, email, first, middle, last):
       
   242   print "Title: %s" % (title)
       
   243   print "Full name: %s %s %s" % (first, middle, last)
       
   244   print "Age: %d nEmail-ID: %s" % (age, email)
       
   245 
       
   246 &gt;&gt;&gt; args = (29, 'johny@example.com')
       
   247 &gt;&gt;&gt; name = {
       
   248         'first': 'Johny',
       
   249         'middle': 'Charles',
       
   250         'last': 'Douglas'
       
   251         }
       
   252 &gt;&gt;&gt; print_report('Employee Report', *args, **name)
       
   253 Title: Employee Report
       
   254 Full name: Johny Charles Douglas
       
   255 Age: 29
       
   256 Email-ID: johny@example.com</pre>
       
   257 </div>
       
   258 <div class="section" title="5.Nested Functions and Scopes">
       
   259 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   260 <a name="id2854624"></a>5.Nested Functions and Scopes</h2></div></div></div>
       
   261 <p id="ch5func_18">Python allows nesting one function inside another. This style of programming
       
   262 turns out to be extremely flexible and powerful features when we use <span class="emphasis"><em>Python
       
   263 decorators</em></span>. We will not talk about decorators is beyond the scope of this
       
   264 course. If you are interested in knowing more about <span class="emphasis"><em>decorator programming</em></span> in
       
   265 Python you are suggested to read:</p>
       
   266 <div class="reference">
       
   267 <div class="titlepage"><hr /></div>http://avinashv.net/2008/04/python-decorators-syntactic-sugar/</div>
       
   268 <div class="reference">
       
   269 <div class="titlepage"><hr /></div>http://personalpages.tds.net/~kent37/kk/00001.html</div>
       
   270 <p id="ch5func_19">However, the following is an example for nested functions in Python:</p>
       
   271 <pre class="programlisting">
       
   272 def outer():
       
   273   print "Outer..."
       
   274   def inner():
       
   275     print "Inner..."
       
   276   print "Outer..."
       
   277   inner()
       
   278 
       
   279 &gt;&gt;&gt; outer()</pre>
       
   280 </div>
       
   281 <div class="section" title="6.map, reduce and filter functions">
       
   282 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   283 <a name="id2854673"></a>6.map, reduce and filter functions</h2></div></div></div>
       
   284 <p id="ch5func_1a">Python provides several built-in functions for convenience. The <span class="strong"><strong>map()</strong></span>,
       
   285 <span class="strong"><strong>reduce()</strong></span> and <span class="strong"><strong>filter()</strong></span> functions prove to be very useful with sequences like
       
   286 <span class="emphasis"><em>Lists</em></span>.</p>
       
   287 <p id="ch5func_1b">The <span class="strong"><strong>map</strong></span> (<span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>sequence</em></span>) function takes two arguments: <span class="emphasis"><em>function</em></span>
       
   288 and a <span class="emphasis"><em>sequence</em></span> argument. The <span class="emphasis"><em>function</em></span> argument must be the name of the
       
   289 function which in turn takes a single argument, the individual element of the
       
   290 <span class="emphasis"><em>sequence</em></span>. The <span class="strong"><strong>map</strong></span> function calls <span class="emphasis"><em>function(item)</em></span>, for each item in the
       
   291 sequence and returns a list of values, where each value is the value returned
       
   292 by each call to <span class="emphasis"><em>function(item)</em></span>. <span class="strong"><strong>map()</strong></span> function allows to pass more than
       
   293 one sequence. In this case, the first argument, <span class="emphasis"><em>function</em></span> must take as many
       
   294 arguments as the number of sequences passed. This function is called with each
       
   295 corresponding element in the each of the sequences, or <span class="strong"><strong>None</strong></span> if one of the
       
   296 sequence is exhausted:</p>
       
   297 <pre class="programlisting">
       
   298 def square(x):
       
   299   return x*x
       
   300 
       
   301 &gt;&gt;&gt; map(square, [1, 2, 3, 4])
       
   302 [1, 4, 9, 16]
       
   303 
       
   304 def mul(x, y):
       
   305   return x*y
       
   306 
       
   307 &gt;&gt;&gt; map(mul, [1, 2, 3, 4], [6, 7, 8, 9])</pre>
       
   308 <p id="ch5func_1c">The <span class="strong"><strong>filter</strong></span> (<span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to
       
   309 the <span class="strong"><strong>map()</strong></span> function. The <span class="strong"><strong>filter</strong></span> function calls <span class="emphasis"><em>function(item)</em></span>, for each
       
   310 item in the sequence and returns all the elements in the sequence for which
       
   311 <span class="emphasis"><em>function(item)</em></span> returned True:</p>
       
   312 <pre class="programlisting">
       
   313 def even(x):
       
   314   if x % 2:
       
   315     return True
       
   316   else:
       
   317     return False
       
   318 
       
   319 &gt;&gt;&gt; filter(even, range(1, 10))
       
   320 [1, 3, 5, 7, 9]</pre>
       
   321 <p id="ch5func_1d">The <span class="strong"><strong>reduce</strong></span> (<span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to
       
   322 <span class="strong"><strong>map</strong></span> function, however multiple sequences are not allowed. The <span class="strong"><strong>reduce</strong></span>
       
   323 function calls <span class="emphasis"><em>function</em></span> with first two consecutive elements in the sequence,
       
   324 obtains the result, calls <span class="emphasis"><em>function</em></span> with the result and the subsequent element
       
   325 in the sequence and so on until the end of the list and returns the final result:</p>
       
   326 <pre class="programlisting">
       
   327 def mul(x, y):
       
   328   return x*y
       
   329 
       
   330 &gt;&gt;&gt; reduce(mul, [1, 2, 3, 4])
       
   331 24</pre>
       
   332 <div class="section" title="6.1.List Comprehensions">
       
   333 <div class="titlepage"><div><div><h3 class="title">
       
   334 <a name="id2854863"></a>6.1.List Comprehensions</h3></div></div></div>
       
   335 <p id="ch5func_1e">List Comprehension is a convenvience utility provided by Python. It is a
       
   336 syntatic sugar to create <span class="emphasis"><em>Lists</em></span>. Using <span class="emphasis"><em>List Comprehensions</em></span> one can create
       
   337 <span class="emphasis"><em>Lists</em></span> from other type of sequential data structures or other <span class="emphasis"><em>Lists</em></span> itself.
       
   338 The syntax of <span class="emphasis"><em>List Comprehensions</em></span> consists of a square brackets to indicate
       
   339 the result is a <span class="emphasis"><em>List</em></span> within which we include at least one <span class="strong"><strong>for</strong></span> clause and
       
   340 multiple <span class="strong"><strong>if</strong></span> clauses. It will be more clear with an example:</p>
       
   341 <pre class="programlisting">
       
   342 &gt;&gt;&gt; num = [1, 2, 3]
       
   343 &gt;&gt;&gt; sq = [x*x for x in num]
       
   344 &gt;&gt;&gt; sq
       
   345 [1, 4, 9]
       
   346 &gt;&gt;&gt; all_num = [1, 2, 3, 4, 5, 6, 7, 8, 9]
       
   347 &gt;&gt;&gt; even = [x for x in all_num if x%2 == 0]</pre>
       
   348 <p id="ch5func_1f">The syntax used here is very clear from the way it is written. It can be
       
   349 translated into english as, "for each element x in the list all_num,
       
   350 if remainder of x divided by 2 is 0, add x to the list."</p>
       
   351 </div>
       
   352 </div>
       
   353 </div>
       
   354 </div></body>
       
   355 </html>
       
   356