Python Programming

Lecture 6 Advanced Functions

6.1 Functions (2)

Variable scope

Variable Scope


 
g_count = 0  # Global
def outer():
    i_count = 2  # Local
  • In Python, module, class, def, lambda can introduce new variable scope, if/elif/else/, try/except, for/while will not introduce new variable scope.

  • Local$\rightarrow$Global


if True:
    msg = 'I am from Shanghai'
print(msg) # We can use msg.

def test():
    msg = 'I am from Shanghai'
print(msg) # error

New Assignment


msg = 'I am from Shanghai'
def test():
    msg = 'I am from Beijing'
    print(msg) 
test()
print(msg)

I am from Beijing
I am from Shanghai



Reference


msg = 'I am from Shanghai'
def test():
    print(msg) 
test()

I am from Shanghai


Modification


msg = 'I am from Shanghai'
def test():
    print(msg) 
    msg = 'I am from Beijing' 
test() 

UnboundLocalError: local variable 'msg' 
referenced before assignment


  • How to modify the variable outside? The global keyword


num = 1
def fun():
    global num
    num = 123
    print(num)
fun()
print(num)

123
123


 


num = 1
def fun():
    print(num)
    global num  
    num = 123
    print(num)
fun()

SyntaxError: name 'num' is used 
prior to global declaration





a = 10
def test():
    a = a + 1
    print(a)
test() # error

a = 10
def test():
    global a 
    a = a + 1
    print(a)
test() # output: 11

a = 10
def test():
    a=10
    a = a + 1
    print(a)
test() # output: 11
print(a) # output: 10

6.2 Functions (3)

arbitrary arguments

def make_pizza(toppings):
    print(toppings)

make_pizza('pepperoni')
  • If we want to pass multiple arguments, we may create a list at first.


x=['mushrooms', 'green peppers', 'extra cheese']
def make_pizza(toppings):
    for y in toppings:
        print(y, end=', ')

make_pizza(x)

def make_pizza(topping_1, topping_2, topping_3):
    print(topping_1, topping_2, topping_3)

make_pizza('mushrooms', 'green peppers', 'extra cheese')
  • However, sometimes we are not sure about the exact number of the arguments.

  • We can pass multiple arguments at once in the following way.


def make_pizza(*toppings):
    print(toppings)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
  • Note that Python packs the arguments into a tuple, even if the function receives only one value.


def make_pizza(*toppings):
    for topping in toppings:
        print("- " + topping)

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

- pepperoni
- mushrooms
- green peppers
- extra cheese
  • Mixing Positional and Arbitrary Arguments

  • If you want a function to accept several different kinds of arguments, the parameter that accepts an arbitrary number of arguments must be placed last in the function definition.


def make_pizza(size, *toppings):
    print(str(size) + "-inch pizza:")
    for topping in toppings:
        print("- " + topping)

make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

16-inch pizza:
- pepperoni
12-inch pizza:
- mushrooms
- green peppers
- extra cheese
  • Using Arbitrary Keyword Arguments


def build_profile(**user_info):
    print(user_info)

build_profile(location='Shanghai',field='Management')

{'location': 'Shanghai', 'field': 'Management'}
  • Using Arbitrary Keyword Arguments


def build_profile(first, last, **user_info):
    for key, value in user_info.items():
        profile[key] = value
    return first, last, profile

user_profile = build_profile('albert', 'einstein',
                            location='princeton',
                            field='physics')
print(user_profile)

('albert', 'einstein', 
{'location': 'princeton', 'field': 'physics'})

def build_profile(*name, **user_info):
    print(name)
    print(user_info)

build_profile('albert', 'einstein',
               location='princeton',
               field='physics')

('albert', 'einstein')
{'location': 'princeton', 'field': 'physics'}
  • As a tradition, we often use *args and **kw

  • Example


def test(x,y=1,*a,**b):
    print(x,y,a,b)

test(1)
test(1,2)
test(1,2,3)
test(1,2,3,4)
test(x=1,y=2)
test(1,a=2)
test(1,2,3,a=4)
test(1,2,3,y=4)

  • Result




1 1 () {}
1 2 () {}
1 2 (3,) {}
1 2 (3, 4) {}
1 2 () {}
1 1 () {'a': 2}
1 2 (3,) {'a': 4}
TypeError: test() got multiple values

6.3 Functions (4)

Comprehension Syntax, Lambda function
Comprehension Syntax
  • Four ways of creating a list


def test1():
    l = []
    for i in range(100):
        l = l + [i]

def test2():
    l = []
    for i in range(100):
        l.append(i)

def test3():
    l = list(range(100))

def test4():
    l = [i for i in range(100)]

[ expression for value in iterable if condition ]


>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
  • map()


def f(x):
    return x * x

y = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])    
print(list(y))

[1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> print(list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

Anonymous function: lambda


def add( x, y ):
    return x + y
 
lambda x, y: x + y
 
lambda x, y = 2: x + y
lambda *z: z

 
>>> a = lambda x, y: x + y
>>> a( 1, 3 )
4
>>> b = lambda x, y = 2: x + y
>>> b( 1 )
3
>>> b( 1, 3 )
4
>>> c = lambda *z: z
>>> c( 10, 'test')
(10, 'test')
  • Sometimes the anonymous function is convenient.

  • It has only one expression. (You do not have to use return)


sum = lambda arg1, arg2: arg1 + arg2

print ("The total is : ", sum( 10, 20 ))
print ("The total is : ", sum( 20, 20 ))

>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

Summary

  • Functions
    • Reading: Python for Everybody, Chapter 10.1-10.5, 10.7-10.8
    • Reading: Python Crash Course, Chapter 8