5. More on functions
5. More on functions
2
Identifiers in Program
• Names of variables, functions, modules can collide with others – same
name used unintentionally (Python allows this)
• Managed using name spaces
• Encapsulation of names through levels of abstraction
• Three levels of encapsulation
• LEGB rule for simple variables
• Qualified names
• modules
3
LEGB
• L: local
• E: Enclosing function definitions
• G: Global
• B: built-in functions
• When Python is looking for meaning attached to a name, it
search the scope in the order: Local, Enclosing, Global, Built-in
>>> x = 42
>>> def afun():
... x = 12 Only creating local var
... print (x)
>>> afun()
12
>>> print (x)
42 4
Enclosing
• Occurs when one function is defined inside another
• Each function definition creates a new scope for variables at that level
Name Scope
• Names defined outside functions have global scope
• Any local names will shadow the global (same name)
• All values & names destroyed after return
6
Scopes
• Described as a series of nested boxes
• To find a match for a given variable, the boxes are examined from
inside out until the name is found
• Lambda create their own local scope
• Thus distinct from surrounding function scope
9
Built-in functions
• Functions that are initially part of any Python program e.g. open, zip,
etc
• Can be overridden in a different scope
• For example, a programmer can define his/her own open.
• However it will prevent access to the standard function i.e. file open
10
dir function
• dir can be used to access a list of names in current scope
• Get global scope in topmost level
>>> z = 12
>>> def dirTest():
... x = 34
... print (dir())
>>> print (dir())
['__builtins__', '__doc__', '__name__', '__package__',
'dirTest', 'pywin', 'z']
>>> dirTest()
['x']
11
dir function
• Can accept an argument
• Return scope of the object
Positional Arguments
13
1 def foo(x, y): Revision
2 print("{} {}" .format(x, y))
3
4 foo(x=3, y=2)
5
6 foo(y=2, x=3)
7
8 foo(3, y=2) 3 2
9 3 2
10 3 2
Keyword arguments
Default arguments
16
Function Parameters Revisited
1 First name: Ken
2 Last name: Thompson
3 Age: 70
4
5
First name: Adele
6
Last name: Goldberg
7 Age: 68
8 Favorite language: Smalltalk
9
10
11 First name: Dennis
12 Last name: Ritchie
Favorite language: C
Died at: 2011
17
Arbitrary Number of Arguments
• Python functions can be flexible to handle different situation by
combination of keyword arguments and default value
• But we can do even better
• Consider a function to add up two numbers
1 # This function adds two numbers together, and prints the sum
2 def adder(num_1, num_2):
3 sum = num_1 + num_2
4 print("The sum of your numbers is {:d}.".format(sum))
5 The sum of your numbers is 3.
6 # Let's add some numbers. The sum of your numbers is 1.
adder(1, 2) The sum of your numbers is -1.
adder(-1, 2)
adder(1, -2)
18
Arbitrary Number of Arguments
• If we pass three arguments to it, the function will has problem
1 def adder(num_1, num_2):
2 sum = num_1 + num_2
3 print("The sum of your numbers is {:d}.".format(sum))
4
5 # Let's add some numbers.
6 adder(1, 2, 3)
21
Arbitrary Number of Arguments
• Let's rewrite our adder() function
1 def adder(num_1, num_2, *nums):
2 sum = num_1 + num_2
3 for num in nums:
4 sum = sum + num
5
6 print("The sum of your numbers is %d." % sum)
7
8 # Let's add some numbers.
9 adder(3,4) The sum of your numbers is 7.
10 adder(1, 2, 3) The sum of your numbers is 6.
11 adder(1,2,3,4,5) The sum of your numbers is 15.
22
Arbitrary Number of Arguments
• Accept i ng an arbi t rary number of keyword argument s i s
al so possi bl e
1 def example_function(arg_1, arg_2, **kwargs): arg_1: a
2 print('\narg_1:', arg_1) arg_2: b
3 print('arg_2:', arg_2) arg_3: {}
4 print('arg_3:', kwargs)
5 arg_1: a
arg_2: b
6 example_function('a', 'b')
arg_3: {'value_3': 'c'}
7 example_function('a', 'b', value_3='c')
8 example_function('a', 'b', value_3='c', value_4='d') arg_1: a
arg_2: b
arg_3: {'value_3': 'c',
'value_4': 'd'}
23
Arbitrary Number of Arguments
• Keyword argument s are st ored as a di ct i onary
24
Exercise
• Can you rewrite the adder() with the following function signature?
25
First Example Rewritten
1 def describe_person(first_name, last_name, **kwargs):
2 print("First name: %s" % first_name.title())
3 print("Last name: %s" % last_name.title())
4 # Optional information:
5 for key in kwargs:
6 print("%s: %s" % (key.title(), kwargs[key]))
7 print("\n")
8
9 describe_person('brian', 'kernighan', favorite_language='C', famous_book='The
10 C Programming Language')
11 describe_person('dennis', 'ritchie', favorite_language='C', died=2011,
12 famous_book='The C Programming Language')
13 describe_person('guido', 'van rossum', favorite_language='Python',
14 company='Dropbox')
15
16
26
Function Parameters
1 First name: Brian
2 Last name: Kernighan
3 Favorite_Language: C
4 Famous_Book: The C Programming Language
5
First name: Dennis
6
Last name: Ritchie
7 Favorite_Language: C
8 Died: 2011
9 Famous_Book: The C Programming Language
10
11 First name: Guido
12 Last name: Van Rossum
Favorite_Language: Python
Company: Dropbox
27
Pickle & Dictionary
• Dictionary is best to pair with Pickle
28
Appendix
Try except
• Similar to the try-catch mechanism in other programming language, python use try-
except-else-finally block to handle exception
def divide(x, y):
try:
result = x // y # Floor Division : Gives only Fractional
except ZeroDivisionError:
print ("Sorry ! You are dividing by zero ")
else:
print ("Yeah ! Your answer is :", result)
divide(3, 2)
divide(3, 0)
divide(3,'1')
>>> Yeah ! Your answer is : 1
>>> Sorry ! You are dividing by zero
> Traceback (most recent call last):
File "COURSE/python/divide.py", line 10, in <module>
divide(3,'1')
File "COURSE/python/divide.py", line 3, in divide
result = x //y
TypeError: unsupported operand type(s) for //: 'int' and 'str'
30
Raise exception
• When the program is running at a point that the current function cannot solve
the problem, we can raise an exception for caller to handle
def divide(x, y):
try:
result = x // y # Floor Division : Gives only Fractional
except ZeroDivisionError:
print ("Sorry ! You are dividing by zero ")
except Exception as e:
raise
else:
print ("Yeah ! Your answer is :", result)
try:
divide(1, 's')
except Exception as e:
print (e)
32