""" 1. Functions declaration - Basic function definition def name(parameter1, parameter2, . . .): ''' Function documentation (optional) ''' body """ # STYLE: It’s a standard practice for multi-line documentation strings to give a synopsis # of the function in the first line (brief), follow this with a blank second line, and end # with the rest of the information. # You can obtain documentation string with: fact.__doc__ def fact(n): """Return the factorial of the given number.""" r = 1 while n > 0: r = r*n n = n - 1 return r ''' A function that doesn’t return a value is called a procedure. All Python procedures are functions; if no explicit return is executed in the procedure body, then the special Python value None is returned. ''' # Assign the result x = fact(4) ''' 2. Function parameter options The simplest way to pass parameters to a function in Python is by position. In the first line of the function, you specify definition variable names for each parameter; when the function is called, the parameters used in the calling code are matched to the function’s parameter variables based on their order. ''' # This method requires that the number of parameters used by the calling code exactly # match the number of parameters in the function definition, or a TypeError exception will # be raised: def power(x, y): r = 1 while y > 0: r = r*x y = y - 1 return r ''' 2.1 Default values Function parameters can have default values, which you declare by assigning a default value in the first line of the function definition, like so: def fun(arg1, arg2=default2, arg3=default3, . . .) Any number of parameters can be given default values. NOTE: Parameters with default values must be defined as the _last_ parameters in the parameter list. ''' # STYLE: See there is not space in default parameters assignment def power(x, y=2): r = 1 while y > 0: r = r * x y = y - 1 return r ''' 2.2 Passing arguments by parameter name This type of argument passing is called key- word passing. ''' power(y=2, x=3) # Keyword passing, in combination with the default argument capability of Python # functions, can be highly useful when you’re defining functions with large numbers of # possible arguments, most of which have common defaults. # Suppose you have: # def list_file_info(size=False, create_date=False, mod_date=False, ...): # ...get file names... # if size: # # code to get file sizes goes here # if create_date: # # code to get create dates goes here # ... # ... # ... # return file_info_structure # Hey do not worry - you do not need to remember all argument positions # # file_info = list_file_info(size=True, mod_date=True) ''' 2.3 Variable numbers of arguments - One way handles the relatively familiar case where you wish to collect an unknown number of arguments at the end of the argument list into a list. - Also you can collect an arbitrary number of keyword-passed arguments, which have no correspondingly named parameter in the function parameter list, into a dictionary. ''' # Prefixing the _final_ parameter name of the function with a * causes all excess non- # keyword arguments in a call of a function to be collected together and assigned as a # tuple to the given parameter. def maximum(*numbers): if len(numbers) == 0: return None else: maxnum = numbers[0] for n in numbers[1:]: if n > maxnum: maxnum = n return maxnum # Here is how we call it: maximum(2, 3, 4, 5) # If the _final_ parameter in the parameter list is prefixed with **, it will collect all # excess keyword-passed arguments into a dictionary. The index for each entry in the # dictionary will be the keyword (parameter name) for the excess argument. def example_fun(x, y, **other): print("x: {0}, y: {1}, keys in 'other': {2}".format(x, y, list(other.keys()))) other_total = 0 for k in other.keys(): other_total = other_total + other[k] print("The total of values in 'other' is {0}".format(other_total)) # Here is an example call: example_fun(2, y="1", foo=3, bar=4) ''' 3. Mutable objects as arguments REMEMBER: Arguments are passed in by object reference! - Immutable objects (such as tuples, strings, and numbers) What is done with a parameter has no effect outside the function. - Mutable objects (for example, a list, dictionary, or class instance), Any change made to the object will change what the argument is referencing outside the function. ''' # Example is always better: def f(n, list1, list2): list1.append("add new value") list2 = ["a", "completely" , "new", "value"] n = n + 1 x = 5 # for n y = [1, 2] # for list1 z = [3, 4] # for list2. Be careful!! f(x, y, z) print x, y, z ''' At the begining: z list2 \ / \ / \ / +-----------+ | [3, 4] | +-----------+ ''' ''' 4. Local and global variables ''' # REMEMBER: Functions define scope! # Any variables in the parameter list of a function, and any variables created within a # function by an assignment (like r = 1 in fact), are local to the function. # You can explicitly make a variable global by declaring it so before the variable is # used, using the _global_ statement. def fun(): global a # use top level a = 1 b = 2 # Let's test it: a = "one" b = "two" fun() print a print b '''' 5. Assigning functions to variables Functions are first class objects! ''' # Functions can be assigned, like other Python objects, to variables, as shown in the fol- # lowing example: def f_to_kelvin(degrees_f): return 273.15 + (degrees_f - 32) * 5 / 9 def c_to_kelvin(degrees_c): return 273.15 + degrees_c abs_temperature = f_to_kelvin abs_temperature(32) abs_temperature = c_to_kelvin abs_temperature(0) # You can place them in lists, tuples, or dictionaries: t = {'FtoK': f_to_kelvin, 'CtoK': c_to_kelvin} t['FtoK'](32) ''' 6. lambda expressions (aka mini functions) Taken directly from LISP! lambda expressions are anonymous little functions that you can quickly define inline. lambda argument1, argument2,... argumentN :expression using arguments Why? Often, a small function needs to be passed to another function. ''' # Explain with examples: import math def square_root(x): return math.sqrt(x) # with lambda (one parameter) square_root = lambda x: math.sqrt(x) # direct call (lambda x: math.sqrt(x))(4) # See more examples in next lecture be patient... ''' 7. Generator(or coroutine) functions Why? Generators functions allow you to declare a function that behaves like an iterator, i.e. it can be used in a loop. ''' # REMEMBER: Generators are memory efficient! Laziness helps for that :) # Compare thies two implementations def firstn(n): num, nums = 0, [] while num < n: nums.append(num) num += 1 return nums sum_of_first_n = sum(firstn(1000000)) def firstn(n): num = 0 while num < n: yield num num += 1 sum_of_first_n = sum(firstn(1000000)) # How could you define function that return all nonnegative integers? def all_naturals(): x = 0 while True: yield x x += 1 33 in all_naturals() ''' 8. Functions in functions - dynamically creating a function (aka lexical closures) ''' # LEGB Rule - order matters # L. Local. Names assigned in any way within a function (def or lambda)), and not # declared global in that function. # E. Enclosing function locals. Name in the local # scope of any and all enclosing functions (def or lambda), form inner to outer. # G. Global (module). Names assigned at the top-level of a module file, or declared global # in a def within the file. # B. Built-in (Python). Names preassigned in the built-in names # module: Python "kernel" # Do you remember that functions creates scope? def make_adder(n=1): def action(x): # inner functions could use all enclosing variables return x + n return action # using lambda def make_adder(n=1): return lambda x: x + n one_adder = maker_adder() #=> one_adder = lambda x: x + 1 one_adder(1) # nested lambdas one_adder = (lambda n: lambda x: x + n)(1) # NOTE: You can't reference inner function directly # With nested functions (closures) you create a function with state (initial value) two_adder = make_adder(2) two_adder(1) ''' 9. Decorators A decorator is just a callable that takes a function as an argument and returns a replacement function. ''' def logger(func): def inner(*args, **kwargs): # all kind of parameters print "Arguments were: %s, %s" % (args, kwargs) return func(*args, **kwargs) # call 'real' function! return inner # Here is how to use it: @logger def foo(x, y=1): return x * y # logger(foo(30)) foo(30) ''' 10. Multi-value return ''' def divide(x, y): quotient = x / y remainder = x % y return quotient, remainder all = divide(22, 7) all, _ = divide(22, 7) q, r = divide(22, 7) ''' 11. __ and __{some}__ functions Naming convention: _ for protected __ for private '''
Thursday, June 25, 2015
Python Crash Course - part two
Subscribe to:
Post Comments (Atom)
algorithms
(1)
cpp
(3)
cv
(1)
daily
(4)
emacs
(2)
freebsd
(4)
java
(3)
javascript
(1)
JSON
(1)
linux
(2)
Lisp
(7)
misc
(8)
programming
(16)
Python
(4)
SICP
(1)
source control
(4)
sql
(1)
думи
(8)
No comments:
Post a Comment