web/html/func.html~
changeset 1 672eaaab9204
parent 0 8083d21c0020
child 2 52d12eb31c30
equal deleted inserted replaced
0:8083d21c0020 1:672eaaab9204
     1 <html>
       
     2 <head>
       
     3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
       
     4 <title></title>
       
     5 <link rel="stylesheet" href="hgbook.css" type="text/css">
       
     6 <meta name="generator" content="DocBook XSL Stylesheets V1.75.1">
       
     7 </head>
       
     8 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><span style="color: red">&lt;html&gt;<span style="color: red">&lt;body&gt;<span style="color: red">&lt;document&gt;<span style="color: red">&lt;title&gt;Functional Approach&lt;/title&gt;</span><span style="color: red">&lt;paragraph&gt;<span class="emphasis"><em>Functions</em></span> allow us to enclose a set of statements and call the function again
       
     9 and again instead of repeating the group of statements everytime. Functions also
       
    10 allow us to isolate a piece of code from all the other code and provides the
       
    11 convenience of not polluting the global variables.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;<span class="emphasis"><em>Function</em></span> in python is defined with the keyword <span style="color: red">&lt;strong&gt;def&lt;/strong&gt;</span> followed by the name
       
    12 of the function, in turn followed by a pair of parenthesis which encloses the
       
    13 list of parameters to the function. The definition line ends with a ':'. The
       
    14 definition line is followed by the body of the function intended by one block.
       
    15 The <span class="emphasis"><em>Function</em></span> must return a value:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def factorial(n):
       
    16   fact = 1
       
    17   for i in range(2, n):
       
    18     fact *= i
       
    19 
       
    20   return fact&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The code snippet above defines a function with the name factorial, takes the
       
    21 number for which the factorial must be computed, computes the factorial and
       
    22 returns the value.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;A <span class="emphasis"><em>Function</em></span> once defined can be used or called anywhere else in the program. We
       
    23 call a fucntion with its name followed by a pair of parenthesis which encloses
       
    24 the arguments to the function.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;The value that function returns can be assigned to a variable. Let's call the
       
    25 above function and store the factorial in a variable:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;fact5 = factorial(5)&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The value of fact5 will now be 120, which is the factorial of 5. Note that we
       
    26 passed 5 as the argument to the function.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;It may be necessary to document what the function does, for each of the function
       
    27 to help the person who reads our code to understand it better. In order to do
       
    28 this Python allows the first line of the function body to be a string. This
       
    29 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
       
    30 to be very handy since there are number of tools which can pull out all the
       
    31 docstrings from Python functions and generate the documentation automatically
       
    32 from it. <span class="emphasis"><em>docstrings</em></span> for functions can be written as follows:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def factorial(n):
       
    33   'Returns the factorial for the number n.'
       
    34   fact = 1
       
    35   for i in range(2, n):
       
    36     fact *= i
       
    37 
       
    38   return fact&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;An important point to note at this point is that, a function can return any
       
    39 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
       
    40 just a collection of values and those values themselves can be of any other
       
    41 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
       
    42 things. So effectively, if a function can return a tuple, it can return any
       
    43 number of values through a tuple&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;Let us write a small function to swap two values:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def swap(a, b):
       
    44   return b, a
       
    45 
       
    46 c, d = swap(a, b)&lt;/literal_block&gt;</span><div class="section" title="1. Function scope">
       
    47 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
    48 <a name="id2981898"></a>1. Function scope</h2></div></div></div>
       
    49 <span style="color: red">&lt;paragraph&gt;The variables used inside the function are confined to the function's scope
       
    50 and doesn't pollute the variables of the same name outside the scope of the
       
    51 function. Also the arguments passed to the function are passed by-value if
       
    52 it is of basic Python data type:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def cant_change(n):
       
    53   n = 10
       
    54 
       
    55 n = 5
       
    56 cant_change(n)&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;Upon running this code, what do you think would have happened to value of n
       
    57 which was assigned 5 before the function call? If you have already tried out
       
    58 that snippet on the interpreter you already know that the value of n is not
       
    59 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>
       
    60 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>
       
    61 the values are manipulated even outside the function:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;&gt;&gt;&gt; def can_change(n):
       
    62 ...   n[1] = James
       
    63 ...
       
    64 
       
    65 &gt;&gt;&gt; name = ['Mr.', 'Steve', 'Gosling']
       
    66 &gt;&gt;&gt; can_change(name)
       
    67 &gt;&gt;&gt; name
       
    68 ['Mr.', 'James', 'Gosling']&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;If nothing is returned by the function explicitly, Python takes care to return
       
    69 None when the funnction is called.&lt;/paragraph&gt;</span>
       
    70 </div>
       
    71 <div class="section" title="2. Default Arguments">
       
    72 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
    73 <a name="id2981970"></a>2. Default Arguments</h2></div></div></div>
       
    74 <span style="color: red">&lt;paragraph&gt;There may be situations where we need to allow the functions to take the
       
    75 arguments optionally. Python allows us to define function this way by providing
       
    76 a facility called <span class="emphasis"><em>Default Arguments</em></span>. For example, we need to write a function
       
    77 that returns a list of fibonacci numbers. Since our function cannot generate an
       
    78 infinite list of fibonacci numbers, we need to specify the number of elements
       
    79 that the fibonacci sequence must contain. Suppose, additionally, we want to the
       
    80 function to return 10 numbers in the sequence if no option is specified we can
       
    81 define the function as follows:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def fib(n=10):
       
    82   fib_list = [0, 1]
       
    83   for i in range(n - 2):
       
    84     next = fib_list[-2] + fib_list[-1]
       
    85     fib_list.append(next)
       
    86   return fib_list&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;When we call this function, we can optionally specify the value for the
       
    87 parameter n, during the call as an argument. Calling with no argument and
       
    88 argument with n=5 returns the following fibonacci sequences:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;fib()
       
    89 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
       
    90 fib(5)
       
    91 [0, 1, 1, 2, 3]&lt;/literal_block&gt;</span>
       
    92 </div>
       
    93 <div class="section" title="3. Keyword Arguments">
       
    94 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
    95 <a name="id2981995"></a>3. Keyword Arguments</h2></div></div></div>
       
    96 <span style="color: red">&lt;paragraph&gt;When a function takes a large number of arguments, it may be difficult to
       
    97 remember the order of the parameters in the function definition or it may
       
    98 be necessary to pass values to only certain parameters since others take
       
    99 the default value. In either of these cases, Python provides the facility
       
   100 of passing arguments by specifying the name of the parameter as defined in
       
   101 the function definition. This is known as <span class="emphasis"><em>Keyword Arguments</em></span>.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;In a function call, <span class="emphasis"><em>Keyword arguments</em></span> can be used for each argument, in the
       
   102 following fashion:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;argument_name=argument_value
       
   103 Also denoted as: keyword=argument
       
   104 
       
   105 def wish(name='World', greetings='Hello'):
       
   106   print "%s, %s!" % (greetings, name)&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;This function can be called in one of the following ways. It is important to
       
   107 note that no restriction is imposed in the order in which <span class="emphasis"><em>Keyword arguments</em></span>
       
   108 can be specified. Also note, that we have combined <span class="emphasis"><em>Keyword arguments</em></span> with
       
   109 <span class="emphasis"><em>Default arguments</em></span> in this example, however it is not necessary:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;wish(name='Guido', greetings='Hey')
       
   110 wish(greetings='Hey', name='Guido')&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;Calling functions by specifying arguments in the order of parameters specified
       
   111 in the function definition is called as <span class="emphasis"><em>Positional arguments</em></span>, as opposed to
       
   112 <span class="emphasis"><em>Keyword arguments</em></span>. It is possible to use both <span class="emphasis"><em>Positional arguments</em></span> and
       
   113 <span class="emphasis"><em>Keyword arguments</em></span> in a single function call. But Python doesn't allow us to
       
   114 bungle up both of them. The arguments to the function, in the call, must always
       
   115 start with <span class="emphasis"><em>Positional arguments</em></span> which is in turn followed by <span class="emphasis"><em>Keyword
       
   116 arguments</em></span>:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def my_func(x, y, z, u, v, w):
       
   117   # initialize variables.
       
   118   ...
       
   119   # do some stuff
       
   120   ...
       
   121   # return the value&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;It is valid to call the above functions in the following ways:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;my_func(10, 20, 30, u=1.0, v=2.0, w=3.0)
       
   122 my_func(10, 20, 30, 1.0, 2.0, w=3.0)
       
   123 my_func(10, 20, z=30, u=1.0, v=2.0, w=3.0)
       
   124 my_func(x=10, y=20, z=30, u=1.0, v=2.0, w=3.0)&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;Following lists some of the invalid calls:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;my_func(10, 20, z=30, 1.0, 2.0, 3.0)
       
   125 my_func(x=10, 20, z=30, 1.0, 2.0, 3.0)
       
   126 my_func(x=10, y=20, z=30, u=1.0, v=2.0, 3.0)&lt;/literal_block&gt;</span>
       
   127 </div>
       
   128 <div class="section" title="4. Parameter Packing and Unpacking">
       
   129 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   130 <a name="id2982116"></a>4. Parameter Packing and Unpacking</h2></div></div></div>
       
   131 <span style="color: red">&lt;paragraph&gt;The positional arguments passed to a function can be collected in a tuple
       
   132 parameter and keyword arguments can be collected in a dictionary. Since keyword
       
   133 arguments must always be the last set of arguments passed to a function, the
       
   134 keyword dictionary parameter must be the last parameter. The function definition
       
   135 must include a list explicit parameters, followed by tuple paramter collecting
       
   136 parameter, whose name is preceded by a <span style="color: red">&lt;strong&gt;*&lt;/strong&gt;</span>, for collecting positional
       
   137 parameters, in turn followed by the dictionary collecting parameter, whose name
       
   138 is preceded by a <span style="color: red">&lt;strong&gt;**&lt;/strong&gt;</span>&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def print_report(title, *args, **name):
       
   139   """Structure of *args*
       
   140   (age, email-id)
       
   141   Structure of *name*
       
   142   {
       
   143       'first': First Name
       
   144       'middle': Middle Name
       
   145       'last': Last Name
       
   146   }
       
   147   """
       
   148 
       
   149   print "Title: %s" % (title)
       
   150   print "Full name: %(first)s %(middle)s %(last)s" % name
       
   151   print "Age: %d\nEmail-ID: %s" % args&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The above function can be called as. Note, the order of keyword parameters can
       
   152 be interchanged:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;&gt;&gt;&gt; print_report('Employee Report', 29, 'johny@example.com', first='Johny',
       
   153                  last='Charles', middle='Douglas')
       
   154 Title: Employee Report
       
   155 Full name: Johny Douglas Charles
       
   156 Age: 29
       
   157 Email-ID: johny@example.com&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The reverse of this can also be achieved by using a very identical syntax while
       
   158 calling the function. A tuple or a dictionary can be passed as arguments in
       
   159 place of a list of <span class="emphasis"><em>Positional arguments</em></span> or <span class="emphasis"><em>Keyword arguments</em></span> respectively
       
   160 using <span style="color: red">&lt;strong&gt;*&lt;/strong&gt;</span> or <span style="color: red">&lt;strong&gt;**&lt;/strong&gt;</span>&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def print_report(title, age, email, first, middle, last):
       
   161   print "Title: %s" % (title)
       
   162   print "Full name: %s %s %s" % (first, middle, last)
       
   163   print "Age: %d\nEmail-ID: %s" % (age, email)
       
   164 
       
   165 &gt;&gt;&gt; args = (29, 'johny@example.com')
       
   166 &gt;&gt;&gt; name = {
       
   167         'first': 'Johny',
       
   168         'middle': 'Charles',
       
   169         'last': 'Douglas'
       
   170         }
       
   171 &gt;&gt;&gt; print_report('Employee Report', *args, **name)
       
   172 Title: Employee Report
       
   173 Full name: Johny Charles Douglas
       
   174 Age: 29
       
   175 Email-ID: johny@example.com&lt;/literal_block&gt;</span>
       
   176 </div>
       
   177 <div class="section" title="5. Nested Functions and Scopes">
       
   178 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   179 <a name="id2982188"></a>5. Nested Functions and Scopes</h2></div></div></div>
       
   180 <span style="color: red">&lt;paragraph&gt;Python allows nesting one function inside another. This style of programming
       
   181 turns out to be extremely flexible and powerful features when we use <span class="emphasis"><em>Python
       
   182 decorators</em></span>. We will not talk about decorators is beyond the scope of this
       
   183 course. If you are interested in knowing more about <span class="emphasis"><em>decorator programming</em></span> in
       
   184 Python you are suggested to read:&lt;/paragraph&gt;</span><span style="color: red">&lt;line_block&gt;<span style="color: red">&lt;line&gt;<div class="reference">
       
   185 <div class="titlepage"><hr></div>http://avinashv.net/2008/04/python-decorators-syntactic-sugar/</div>&lt;/line&gt;</span><span style="color: red">&lt;line&gt;<div class="reference">
       
   186 <div class="titlepage"><hr></div>http://personalpages.tds.net/~kent37/kk/00001.html</div>&lt;/line&gt;</span>&lt;/line_block&gt;</span><span style="color: red">&lt;paragraph&gt;However, the following is an example for nested functions in Python:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def outer():
       
   187   print "Outer..."
       
   188   def inner():
       
   189     print "Inner..."
       
   190   print "Outer..."
       
   191   inner()
       
   192 
       
   193 &gt;&gt;&gt; outer()&lt;/literal_block&gt;</span>
       
   194 </div>
       
   195 <div class="section" title="6. map, reduce and filter functions">
       
   196 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
       
   197 <a name="id2982258"></a>6. map, reduce and filter functions</h2></div></div></div>
       
   198 <span style="color: red">&lt;paragraph&gt;Python provides several built-in functions for convenience. The <span style="color: red">&lt;strong&gt;map()&lt;/strong&gt;</span>,
       
   199 <span style="color: red">&lt;strong&gt;reduce()&lt;/strong&gt;</span> and <span style="color: red">&lt;strong&gt;filter()&lt;/strong&gt;</span> functions prove to be very useful with sequences like
       
   200 <span class="emphasis"><em>Lists</em></span>.&lt;/paragraph&gt;</span><span style="color: red">&lt;paragraph&gt;The <span style="color: red">&lt;strong&gt;map&lt;/strong&gt;</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>
       
   201 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
       
   202 function which in turn takes a single argument, the individual element of the
       
   203 <span class="emphasis"><em>sequence</em></span>. The <span style="color: red">&lt;strong&gt;map&lt;/strong&gt;</span> function calls <span class="emphasis"><em>function(item)</em></span>, for each item in the
       
   204 sequence and returns a list of values, where each value is the value returned
       
   205 by each call to <span class="emphasis"><em>function(item)</em></span>. <span style="color: red">&lt;strong&gt;map()&lt;/strong&gt;</span> function allows to pass more than
       
   206 one sequence. In this case, the first argument, <span class="emphasis"><em>function</em></span> must take as many
       
   207 arguments as the number of sequences passed. This function is called with each
       
   208 corresponding element in the each of the sequences, or <span style="color: red">&lt;strong&gt;None&lt;/strong&gt;</span> if one of the
       
   209 sequence is exhausted:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def square(x):
       
   210   return x*x
       
   211 
       
   212 &gt;&gt;&gt; map(square, [1, 2, 3, 4])
       
   213 [1, 4, 9, 16]
       
   214 
       
   215 def mul(x, y):
       
   216   return x*y
       
   217 
       
   218 &gt;&gt;&gt; map(mul, [1, 2, 3, 4], [6, 7, 8, 9])&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The <span style="color: red">&lt;strong&gt;filter&lt;/strong&gt;</span> (<span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to
       
   219 the <span style="color: red">&lt;strong&gt;map()&lt;/strong&gt;</span> function. The <span style="color: red">&lt;strong&gt;filter&lt;/strong&gt;</span> function calls <span class="emphasis"><em>function(item)</em></span>, for each
       
   220 item in the sequence and returns all the elements in the sequence for which
       
   221 <span class="emphasis"><em>function(item)</em></span> returned True:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def even(x):
       
   222   if x % 2:
       
   223     return True
       
   224   else:
       
   225     return False
       
   226 
       
   227 &gt;&gt;&gt; filter(even, range(1, 10))
       
   228 [1, 3, 5, 7, 9]&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The <span style="color: red">&lt;strong&gt;reduce&lt;/strong&gt;</span> (<span class="emphasis"><em>function</em></span>, <span class="emphasis"><em>sequence</em></span>) function takes two arguments, similar to
       
   229 <span style="color: red">&lt;strong&gt;map&lt;/strong&gt;</span> function, however multiple sequences are not allowed. The <span style="color: red">&lt;strong&gt;reduce&lt;/strong&gt;</span>
       
   230 function calls <span class="emphasis"><em>function</em></span> with first two consecutive elements in the sequence,
       
   231 obtains the result, calls <span class="emphasis"><em>function</em></span> with the result and the subsequent element
       
   232 in the sequence and so on until the end of the list and returns the final result:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;def mul(x, y):
       
   233   return x*y
       
   234 
       
   235 &gt;&gt;&gt; reduce(mul, [1, 2, 3, 4])
       
   236 24&lt;/literal_block&gt;</span><div class="section" title="6.1. List Comprehensions">
       
   237 <div class="titlepage"><div><div><h3 class="title">
       
   238 <a name="id2982429"></a>6.1. List Comprehensions</h3></div></div></div>
       
   239 <span style="color: red">&lt;paragraph&gt;List Comprehension is a convenvience utility provided by Python. It is a
       
   240 syntatic sugar to create <span class="emphasis"><em>Lists</em></span>. Using <span class="emphasis"><em>List Comprehensions</em></span> one can create
       
   241 <span class="emphasis"><em>Lists</em></span> from other type of sequential data structures or other <span class="emphasis"><em>Lists</em></span> itself.
       
   242 The syntax of <span class="emphasis"><em>List Comprehensions</em></span> consists of a square brackets to indicate
       
   243 the result is a <span class="emphasis"><em>List</em></span> within which we include at least one <span style="color: red">&lt;strong&gt;for&lt;/strong&gt;</span> clause and
       
   244 multiple <span style="color: red">&lt;strong&gt;if&lt;/strong&gt;</span> clauses. It will be more clear with an example:&lt;/paragraph&gt;</span><span style="color: red">&lt;literal_block&gt;&gt;&gt;&gt; num = [1, 2, 3]
       
   245 &gt;&gt;&gt; sq = [x*x for x in num]
       
   246 &gt;&gt;&gt; sq
       
   247 [1, 4, 9]
       
   248 &gt;&gt;&gt; all_num = [1, 2, 3, 4, 5, 6, 7, 8, 9]
       
   249 &gt;&gt;&gt; even = [x for x in all_num if x%2 == 0]&lt;/literal_block&gt;</span><span style="color: red">&lt;paragraph&gt;The syntax used here is very clear from the way it is written. It can be
       
   250 translated into english as, "for each element x in the list all_num,
       
   251 if remainder of x divided by 2 is 0, add x to the list."&lt;/paragraph&gt;</span>
       
   252 </div>
       
   253 </div>&lt;/document&gt;</span>&lt;/body&gt;</span>&lt;/html&gt;</span></body>
       
   254 </html>