240 likes | 425 Views
Chapter 12-13 Function Basics. CSC1310 Fall 2009. Function. In simple terms, a function (subroutine, procedure) is a package of code ( a set of statements ) that can be called repeatedly with different inputs ( parameters ) and outputs each time.
E N D
Chapter 12-13 Function Basics CSC1310 Fall 2009
Function • In simple terms, a function (subroutine, procedure) is a package of code (a set of statements) that can be called repeatedly with different inputs (parameters) and outputs each time. • In Python, function is an object which is recorded explicitly at program execution time.
Why Use Function? • Code Reuse: Functions allows us to group and generalize code to be used arbitrarily many times after it is defined. • Procedural decomposition: Functions also provide a tool for splitting systems into pieces that have a well-defined role (one function for each subtask).
def Statement • The def statement creates a function object and assigns it to a name. • General format: def <name> (arg1,arg2, … argN): <statements> return <value> • Python executes body (statement block) each time the function is called. • The argument names will be assigned with the objects passed in the parenthesis at the point of a call. • return ends function call and sends a result back to a caller.
def Runs at Runtime • The def is true executable statement: • Creates and assigns a new function object to a name at a runtime • It is a statement: it can be even nested. >>>k=int(raw_input()) >>>if k==1: def func(): print ”One” else: def func(): print “Not one” >>>print func() • The def is like an = statement. >>>othername=func >>print othername()
Function Example • Definition (def) creates a function • Call – an expression to run the function’s body >>>def pow(x,y): value=x+y return value >>>print pow(2,3) >>>print pow(‘abc’,’345’) # functions are typeless
Polymorphism • Polymorphism is a type-dependent behavior: the meaning of operations depends on the objects being operated upon. • As long as objects support the expected protocol (interface), they can be processed by the function (expected methods and operators, compatible with function’s logic). • If objects do not support interface, Python raises an exception automatically. • Python vs Java, C++: your code is not supposed to care about specific data types (we code to object interfaces, not data type.)
Example: Intersecting Sequences >>>def intersect(x,y): res=[] # local variable for z in x: if z in y: res.append(z) return res • You can run code as many times as you want. • It is general to work on any two sequences. • You need to change code only in one place. • It can be imported and reused by any other program.
Intersecting Sequences: Call >>>s1,s2=‘Wiki’, ’wiki’ >>>intersect(s1,s2) >>>print intersect([1,2,3], (1,4)) >>>print intersect([1,2,3], (4))
Scope Rules • Namespace is the place where names live • The location of name’s assignment defines the scope of the name visibility. • Names defined inside a def can be seen only by the code inside the def. • Names defined inside a def not clash with variables outside the def, even if the same name is used elsewhere.
Scope Basic • The enclosing module is a global scope. • The global scope spans a single file only. • Each call to a function is a new local scope. • Assigned names are local, unless declared global. • All names are either local, or global, or built-ins. • Name resolution: the LEGB Rule: name references search at most at fours scopes: • Local • Enclosing functions (if any) • Global • Built-in.
global Statement • Global names must be declared only if used in a function. • Global names may be referenced in a function without being declared. • global <name1,name2,…nameN> >>>X=88 >>>def func(): global X X=99 >>>func() >>>print X
Nested Functions • Within a function: • Assignment: X=value creates or changes name x in the current local scope by default. If X is declared global within a function, it creates or changes X in the enclosing module’s scope instead. • Reference: X looks for a name in the current local scope (function), then in the local scopes of all lexically enclosing functions from inner to outer (if any), then in the current global scope (the module file), and finally in built-in scope. global declaration makes the search begin in the global scope instead.
Passing Arguments • Arguments are passed by automatically assigning objects to a local names. • Assigning to arguments’ names inside a function doesn’t affect the caller (“by value”). • Changing a mutable object argument in a function may impact a caller (“by pointer”). >>>def change(x, y): x=2; y[0]=‘hi’ >>>x=1;L=[1,’a’] >>>change(x,L) >>>print x,L
Avoiding Mutable Arguments Changes • We can copy the list at the point of the call >>>L=[1,’a’] >>>change(x,L[:]) # pass a copy • We can copy list within the function itself, if we never want to change passed-in objects. >>>def change(x, y): y=y[:] x=2; y[0]=‘hi’ • Both variants above only prevent changes from impacting a caller. • We can convert to immutable objects. >>>L=[1,’a’] >>>change(x,tuple(L)) # pass a tuple
Simulating Output Parameters • return sends back any sort of object • It could return multiple values, by packaging them in tuple. >>>def swap(x,y): y=x+y x=y-x y=y-x return x,y >>>a,b=swap(3,5) >>>print a,b
Special Argument Matching Modes • Positional: matched left to right. • Keywords: matched by the argument name. Callers can specify which argument is to receive a value by specifying the argument’s name in the call with a name=value syntax. • Varargs: catch unmatched positional or keyword arguments. Function can use special arguments preceded with a * characters to collect arbitrarily extra arguments. • Defaults: specify values for arguments that are not passed using a name=value syntax.
Function Argument-Matching Forms • Positional: matched left to right. def func(name) func(value) • Keywords: matched by the argument name. def func(name) func(name=value) • Varargs: catch unmatched arguments. def func(*name) # match remaining positional # args(in a tuple) def func(**name) # match remaining keyword # args(in a dictionary) • Defaults: specify values for arguments that are not passed def func(name=value)
Keyword Examples >>> def f(a,b,c): print a,b,c >>>f(1,2,3) # by position >>>f(c=3,b=2,a=1) # keyword args >>>f(1,c=3,b=2) #mix positional and keyword args
Keyword and Default Examples • Keywords: • Self-documenting • In conjunction with defaults >>>def f(a,b=2,c=1):print a,b,c >>>f(1) >>>f(a=1) >>>f(2,4) >>>f(2,4,5) >>>f(2,c=6)
Arbitrary Argument Examples • Collect unmatched positional arguments into a tuple: >>>def f(*args): print args >>>f() >>>f(1) >>>f(1,2,3,4) • Collect unmatched keyword arguments into a dictionary: >>>def f(**args): print args >>>f() >>>f(a=1,b=2) >>>f(b=1,c=2,a=3,d=4)
Flexible Signature >>>def f(a,*pargs,**krags): print a,pargs,kargs >>>f(1,2,3,x=1,y=‘234’)
Min Example • Make a function that compute a minimum value from: • An arbitrary set of element (*args). • Arbitrary set of object datatypes(polymorphism). >>>def min1(*args): res=args[0] for arg in args[1:]: if arg<res: res=arg return arg >>>def min2(first,*rest): for arg in rest: if arg<first: first=arg return first >>>def min3(*args): tmp=list(args); tmp.sort(); return tmp[0]
Argument Matching • In a call, all keyword arguments must appear after all non-keyword arguments. • In a function header, *name must appear after normal arguments and defaults, **name must appear last. • Steps for assigning done by Python: • Assign non-keyword arguments by position. • Assign keyword args by matching names. • Assign extra non-keyword args to *name tuple • Assign extra keyword to **name dictionary. • Assign default values to unassigned args in header.