Ch5 Functions
Chapter 5: Functions in Python¶
Functions are the building blocks of readable, maintainable, and reusable code. They allow you to encapsulate a task into a single, cohesive unit of work that can be used repeatedly throughout your programs. In this chapter, we delve into functions in Python, exploring how to define them
, pass arguments
, return values
, and leverage advanced features to create efficient and powerful code.
1. Defining and Calling a Function¶
- The
def
keyword introduces a function definition, followed by the function name and the parenthesized list of parameters. - The statements that form the body of the function start at the next line and must be indented.
- The
return
statement exits the function, optionally passing back a value to the caller.
def greet(name):
"""Display a simple greeting."""
return f"Hello, {name}!"
# Call the function with an argument
print(greet("Alice"))
Hello, Alice!
2. Provide docstring to functions¶
Using the following method to get access to the documents of functions
help()
function.__doc__
def my_max(x,y):
'''
get the bigger number between 2 numbers
my_max(x,y)
return the larger number between x and y
'''
z = x if x > y else y
return z
help(my_max)
Help on function my_max in module __main__: my_max(x, y) get the bigger number between 2 numbers my_max(x,y) return the larger number between x and y
print(my_max.__doc__)
get the bigger number between 2 numbers my_max(x,y) return the larger number between x and y
3. Multiple Returns¶
- Python would automatically transfer them into a
tuple
def sum_and_avg(list):
my_sum = 0
count = 0
for e in list:
if isinstance(e,int) or isinstance(e,float):
count += 1
my_sum += e
return my_sum, my_sum / count
my_list = [20,15,2.8,'a',35,5.9,-1.8]
tp = sum_and_avg(my_list)
print(tp)
(76.9, 12.816666666666668)
s,avg = sum_and_avg(my_list)
print(s)
print(avg)
76.9 12.816666666666668
4. Recursive Function¶
$f(0) = 1, f(1) = 4 , f(n+2) = 2 * f(n+1) + f(n)$
def fn(n):
if n == 0:
return 1
elif n == 1:
return 4
else:
return 2 * fn(n-1) + fn(n-2)
print('f(10) = ', fn(10))
f(10) = 10497
def factorial(n):
if n <= 1:
return 1
else:
return n * factorial(n-1)
factorial(6)
720
4.1 Tower of Hanoi¶
def hanoi(n,x,y,z):
'''
x indicates the source block, y indicates the empty block, z indicates the target block
'''
if n == 1:
print(x,'-->',z)
else:
hanoi(n-1,x,z,y)
print(x,'-->',z)
hanoi(n-1,y,x,z)
hanoi(2,'1','2','3')
1 --> 2 1 --> 3 2 --> 3
5. Multiple input parameters¶
- No keyword multiple inputs could be regarded as a
tuple
- Multiple inputs with keywords would be regarded as a
dictionary
def test(a,*books):
print(books)
for b in books:
print(b)
print(a)
test(5,'Crazy Java','Crazy Python','Crazy PHP')
('Crazy Java', 'Crazy Python', 'Crazy PHP') Crazy Java Crazy Python Crazy PHP 5
def test(*books,num):
print(books)
for b in books:
print(b)
print(num)
test('Crazy Python','Crazy Java','Crazy PHP',num = 20)
('Crazy Python', 'Crazy Java', 'Crazy PHP') Crazy Python Crazy Java Crazy PHP 20
def test(x,y,z=3,*books,**scores):
print(x,y,z)
print(books)
print(scores)
test(1,2,3,'Crazy Java','Crazy Python', English = 94, Math = 89)
1 2 3 ('Crazy Java', 'Crazy Python') {'English': 94, 'Math': 89}
test(1,2,'Crazy Java','Crazy Python', English = 94, Math = 89)
1 2 Crazy Java ('Crazy Python',) {'English': 94, 'Math': 89}
test(1,2, English = 94, Math = 89)
1 2 3 () {'English': 94, 'Math': 89}
6. Reversed parameters input¶
*
before a list in Python is used to unpack the list when passing it as an argument to a function.- This means that each element of the list is passed as a separate argument to the function.
def test(name,message):
print('User Name:',name)
print('Message is',message)
my_list = ['Jack','Where is my shoes?']
test(*my_list)
User Name: Jack Message is Where is my shoes?
def foo(name,*nums):
print('Name is',name)
print('Number is',nums)
my_tuple = (1,2,3)
foo('fkit',*my_tuple)
Name is fkit Number is (1, 2, 3)
- The double asterisk (
**
) before a dictionary in Python is used to unpack the dictionary into keyword arguments when passing it to a function. - This means that each key-value pair in the dictionary is passed as a named argument to the function, with the keys acting as the argument names and the corresponding values as the argument values.
def greet(first_name, last_name):
print(f"Hello, {first_name} {last_name}!")
user_info = {"first_name": "John", "last_name": "Doe"}
greet(**user_info)
Hello, John Doe!
def bar(book,price,desc):
print(book, 'With the price of', price)
print('Description is',desc)
my_dict = {'price':89,'book':'Crazy Python','desc':'This is a book for teaching how to use python'}
bar(**my_dict)
Crazy Python With the price of 89 Description is This is a book for teaching how to use python
7. Parameter passing mechanism¶
In python, parameters for functions are passing by value
def swap(a,b):
a,b = b,a
print('Within swap function, a is',a,'b is',b)
a = 6
b = 9
swap(a,b)
print('After swap function, a is',a,'b is',b)
Within swap function, a is 9 b is 6 After swap function, a is 6 b is 9
Careful for inputting list
or dictionary
It is also passing by value, but this value is a address index, so the outputs would be changed
def swap(dw):
dw['a'],dw['b'] = dw['b'],dw['a']
print('Within swap function, a is',dw['a'],'b is',dw['b'])
dw = {'a':6,'b':9}
swap(dw)
print('After swap function, a is',dw['a'],'b is',dw['b'])
Within swap function, a is 9 b is 6 After swap function, a is 9 b is 6
8. The work domain of Variables¶
All three functions would pack the variables into a dictionary
globals()
: Return all variablslocals()
: Return variables within a local domainvars(object)
: Return variables within a object domain
Only the change in the global dictionary would be saved
def test():
age = 20
print(age)
print(locals())
print(locals()['age'])
locals()['age'] = 12
print('After changing through locals(), age is',age)
age = 12
print('After changing through age=12, age is',locals()['age'])
globals()['x'] = 19
x = 5
y = 20
# print(globals())
# print(locals())
print('3',x)
print('4',globals()['x'])
globals()['x'] = 39
print('5',x)
locals()['x'] = 99
print('6',x)
test()
print('7',x)
3 5 4 5 5 39 6 99 20 {'age': 20} 20 After changing through locals(), age is 20 After changing through age=12, age is 12 7 19
- Variables outsides of functions would be regarded as global variables
- But we could not modify their value within the functions
name = 'Jack'
def test():
print(name)
test()
print(name)
Jack Jack
name = 'Jack'
def test():
print(globals()['name'])
name = 'Betty'
test()
print(name)
Jack Jack
But we still could define a global variable within a function
name = 'Jack'
def test():
global name
print(name)
name = 'Betty'
test()
print(name)
Jack Betty
9. Local Functions¶
- In default, local functions are hidden for outsides, only work within the enclosing domain.
- We could return the local function to call it in outsides
def get_math_func(types,nn):
def square(n):
return n*n
def cube(n):
return n*n*n
def factorial(n):
if n <= 1:
return 1
else:
return n * factorial(n-1)
if types == 'square':
return square(nn)
elif types == 'cube':
return cube(nn)
else:
return factorial(nn)
print(get_math_func('square',3))
print(get_math_func('cube',3))
print(get_math_func('',3))
9 27 6
Python provide nonlocal
to access local variables with the enclosing domain for local functions
def foo():
name = 'Jack'
def bar():
nonlocal name
print(name)
name = 'Betty'
bar()
print(name)
foo()
Jack Betty
10. lambda
expression¶
The name of local functions is not very important in some cases, so we could use lambda
expression to simplify them.
10.1 Use lambda
expressions to substitute local functions¶
Actually, lambda
is a one line function without name, the following two lines is same
lambda x,y: x + y
def add(x,y): return x + y
def get_math_func(types):
if types == 'square':
return lambda n: n*n
elif types == 'cube':
return lambda n: n*n*n
else:
return lambda n: (1+n) * n /2
math_func = get_math_func('cube')
print(math_func(5))
math_func = get_math_func('square')
print(math_func(5))
math_func = get_math_func('other')
print(math_func(5))
125 25 15.0
10.2 The format of lambda
expression¶
lambda [parameter_list]: expression
lambda x,y : x+y
Combine
map()
andlambda()
together
x = map(lambda x: x**2, range(8))
print([e for e in x])
[0, 1, 4, 9, 16, 25, 36, 49]
y = map(lambda x: x*x if x % 2 == 0 else 0, range(8))
print([e for e in y])
[0, 0, 4, 0, 16, 0, 36, 0]
def bubble_sort(my_lst):
for index1,ele1 in enumerate(my_lst):
for index2,ele2 in enumerate(my_lst[:-1]):
if ele1 < ele2:
my_lst[index1],my_lst[index2] = my_lst[index2],my_lst[index1]
return my_lst
bubble_sort([10,4,8,91,69,6156,3,0,-10,-42,37])
[-42, -10, 0, 3, 4, 8, 10, 37, 69, 91, 6156]
11.2 Leap Year¶
def is_leap(year):
if (int(year) % 4 ==0) and (int(year) % 100 > 0):
return True
elif (int(year) % 400 ==0):
return True
else:
return False
print(is_leap(1900))
print(is_leap(1896))
False True
11.3 Count String, numbers, space and others¶
def count_str_char(my_list):
digit_num = 0
space_num = 0
other_num = 0
char_num = 0
for c in my_list:
c = str(c)
if c.isdigit(): digit_num += 1
elif c.isalpha(): char_num += 1
elif c.isspace(): space_num += 1
else: other_num += 1
return {'Number of Character':char_num, 'Number of Space': space_num,
'Number of digitals':digit_num,'Number of Others': other_num}
count_str_char([2,4968,8,9,' ',' ',' ',' ','A','f','#','$','dsfs'])
{'Number of Character': 3, 'Number of Space': 4, 'Number of digitals': 4, 'Number of Others': 2}
11.4 Remove repeated elements¶
set
{}.fromkeys()
set([2,2,2,5,'a','sffsf',49,7,9])
{2, 49, 5, 7, 9, 'a', 'sffsf'}
{}.fromkeys([2,2,2,5,'a','sffsf',49,7,9]).keys()
dict_keys([2, 5, 'a', 'sffsf', 49, 7, 9])
11.5 Matrix and Transpose¶
def matrix_transpose(n):
my_matrix = [[0] * n]
for time in range(1,n):
my_matrix += [[0]* n]
for row in range(0,n):
for col in range(0,n):
my_matrix[row][col] = row * n + col + 1
for row in my_matrix:
for ele in row:
print(ele,end=' ')
print()
print('--------------------')
for row in range(0,n):
for col in range(0,n):
print(my_matrix[col][row],end=' ')
print()
matrix_transpose(3)
1 2 3 4 5 6 7 8 9 -------------------- 1 4 7 2 5 8 3 6 9