赞
踩
本章要点:
函数是Python程序的重要组成单位,一个Python程序可以由很多个函数组成。
函数可以接受0个或多个参数,返回0个或多个值。
定义函数语法:
- def 函数名(形参列表) :
- //有零个到多条可执行语句组成的函数
- [return [返回值]]
例如:
- #*****************************
- #***程序名称:function_test.py
- #***程序功能:定义两个函数
- #***编写日期:2019-5-16
- #*****************************
- #定义一个函数,声明两个形参
- def my_max(x,y):
- #定义一个变量z,该变量等于x,y中较大的值
- z = x if x > y else y
- #返回变量z
- return z
- #定义一个函数,声明一个形参
- def say_hi(name):
- print("====正在执行say_hi()函数====")
- return name + ",你好!"
- a = 6
- b = 9
- #调用my_max()函数,将函数返回值赋值给result变量
- result = my_max(a,b)
- print("result:",result)
- #调用say_hi()函数,直接输出函数的返回值
- print(say_hi("孙悟空"))
'运行
一共两种方式:
(1)通过help()函数查看函数的说明文档;
(2)通过函数的__doc__属性访问函数的说明文档。(注意doc前后各是两个英文"_")
例如:
- #*****************************
- #***程序名称:function_doc.py
- #***程序功能:为函数编写说明文档
- #***编写日期:2019-5-16
- #*****************************
- def my_max(x,y):
- '''
- 获取两个数值之间较大数的函数
- my_max(x,y)
- 返回x,y两个参数之间较大的那个数
- '''
- #定义一个变量z,该变量等于x,y中较大的值
- z = x if x > y else y
- #返回变量z
- return z
- #使用help()函数查看my_max()的帮助文档
- help(my_max)
- #__doc__两边一定要是双下划线,否则报错!(_doc_这是错的!)
- print(my_max.__doc__)
'运行
如果程序需要多个返回值,则即可将多个值包装成列表之后返回,也可直接返回多个值。如果返回多个值,Python会自动将多个返回值封装成元组。
例如:
- #*****************************
- #***程序名称:multi_return.py
- #***程序功能:函数直接返回多个值的情形
- #***编写日期:2019-5-16
- #*****************************
- def sum_and_avg(list):
- sum = 0
- count = 0
- for e in list:
- #如果元素e是数值
- if isinstance(e,int) or isinstance(e,float):
- count += 1
- sum += e
- return sum , sum / count
- my_list = [20,15,2.8,'a',35,5.9,-1.8]
- #获取sum_and_avg函数返回的多个值,多个返回值被封装成元组
- tp = sum_and_avg(my_list)
- print(tp)
- #使用序列解包来获取多个返回值
- s , avg = sum_and_avg(my_list)
- print(s)
- print(avg)
'运行
定义:在一个函数体内调用它自身,被称为函数递归。
函数递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。
注意:递归一定要向已知方向进行。
例如:
- #*****************************
- #***程序名称:recursive.py
- #***程序功能:已知有一个数列:f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),
- #其中n是大于0的整数,求f(10)的值。
- #***编写日期:2019-5-16
- #*****************************
- def fn(n):
- if n == 0 :
- return 1
- elif n == 1 :
- return 4
- else :
- #在函数体中调用它自身,就是函数递归
- return 2 * fn(n-1) + fn(n-2)
- #输出fn(10)的结果
- print("fn(10)的结果是:",fn(10))
'运行
——谁调用函数,谁负责传入参数。
(1)位置参数——按照位置传入的参数。
(2)关键字参数——根据参数名传入的参数值。在关键字参数之后的只能是关键字参数。关键字参数必须位于位置参数后面。
例如:
- #*****************************
- #***程序名称:named_param_test.py
- #***程序功能:函数的参数
- #***编写日期:2019-5-16
- #*****************************
- #定义一个函数
- def girth(width,height):
- print("width:",width)
- print("height:",height)
- return 2 * (width + height)
- #传统调用函数的方式,根据位置传入参数值
- print(girth(3.5,4.8))
- print("----------------------")
- #根据关键字参数传入参数值
- print(girth(width = 3.5,height = 4.8))
- print("----------------------")
- #使用关键字参数时可以交换位置
- print(girth(height = 4.8,width = 3.5))
- print("----------------------")
- #部分使用关键字参数,部分使用位置参数
- print(girth(3.5,height = 4.8))
'运行
语法格式:
形参名 = 默认值
注意:Python要求将带默认值的参数定义在形参列表的最后。
例如:
- #*****************************
- #***程序名称:default_param_test.py
- #***程序功能:为函数的形参指定默认值
- #***编写日期:2019-5-18
- #*****************************
- #为两个参数指定默认值
- def say_hi(name = "孙悟空",message = "欢迎来到疯狂软件"):
- print(name, ",你好!")
- print("消息是:",message)
- #全部使用默认参数
- say_hi()
- print("---------------------------")
- #只有message参数使用默认值
- say_hi("白骨精")
- print("---------------------------")
- #两个参数都不使用默认值
- say_hi("白骨精","欢迎学习Python")
- print("---------------------------")
- #只有name参数使用默认值
- say_hi(message = "欢迎学习Python")
'运行
有例如:
- #*****************************
- #***程序名称:default_param_test2.py
- #***程序功能:Python要求将带有默认值的
- #参数(关键字参数)定义在形参列表的最后
- #***编写日期:2019-5-18
- #*****************************
- #定义一个打印三角形的函数,有默认值的参数必须放在后面
- def printTriangle(char , height = 5):
- for i in range(1,height + 1 ): #控制打印行数
- #先打印一排空格
- for j in range(height - i):
- print(' ', end = '')
- #在打印一排特殊字符
- for j in range(2 * i - 1):
- print(char , end = '')
- print() #换行
- printTriangle('@', 6)
- printTriangle('#', height = 7)
- printTriangle(char = '*')
'运行
(1)在形参前面添加一个星号(*),该参数可接受多个参数值,并且被当成元组传入。
例如:
- #*****************************
- #***程序名称:varargs.py
- #***程序功能:定义一个形参个数可变的函数
- #***编写日期:2019-5-18
- #*****************************
- #定义了支持参数收集的函数
- def test(a , *books):
- print(books)
- #books被当成元组处理
- for b in books :
- print(b)
- #输出整数变量a的值
- print(a)
- #调用test()函数
- test(5 , "疯狂iOS讲义","疯狂Android讲义")
'运行
Python要求一个函数最多只能带一个支持“普通”参数收集的形参。
例如:
- #*****************************
- #***程序名称:varargs2.py
- #***程序功能:Python要求一个函数最多只能带一个支持“普通”参数收集的形参
- #***编写日期:2019-5-18
- #*****************************
- #定义了支持参数收集的函数
- def test(*books , num):
- print(books)
- #books被当成元组处理
- for b in books:
- print(b)
- print(num)
- #调用test()函数
- test("疯狂iOS讲义","疯狂Android讲义",num = 20) #使用关键字参数
'运行
(2)Python还可以收集关键字参数,需要在参数前面添加两个星号(**)。
例如:
- #*****************************
- #***程序名称:varargs3.py
- #***程序功能:Python还可以收集关键字参数,需要在参数前加**。
- #Python会将这种关键字参数收集成字典。
- #***编写日期:2019-5-18
- #*****************************
- #定义了支持参数收集的函数
- def test(x , y , z = 3 ,*books , **scores):
- print(x,y,z)
- print(books)
- print(scores)
- test(1,2,3,"疯狂iOS讲义","疯狂Android讲义",语文=89,数学=94)
- '''运行结果如下:
- 1 2 3
- ('疯狂iOS讲义', '疯狂Android讲义')
- {'语文': 89, '数学': 94}
- '''
- print("--------------------------")
- test(1,2,"疯狂iOS讲义","疯狂Android讲义",语文=89,数学=94)
- print("--------------------------")
- #让z参数的默认值发挥作用,books参数将是一个空元组
- test(1,2,语文=89,数学=94)
'运行
定义:指的是在程序已有列表、元组、字典等对象的前提下,把它们的元素“拆开”后传给函数的参数。
注意:逆向参数收集需要在传入的列表、元组参数之前添加一个星号,在字典参数之前添加两个星号。 |
例如:
- #*****************************
- #***程序名称:varargs4.py
- #***程序功能:逆向参数收集——指的是在程序已有列表、元组、字典等对象
- #的前提下,把它们的元素“拆开”后传递给函数的参数。
- #注意:列表、元组参数之前添加*,字典参数之前添加**
- #***编写日期:2019-5-18
- #*****************************
- def test(name , message):
- print("用户是:", name)
- print("欢迎信息是:",message)
- my_list = ['孙悟空' , '欢迎来疯狂软件']
- test(*my_list)
- print("--------------------------")
- def foo(name , *nums):
- print("name参数:",name)
- print("nums参数:",nums)
- my_tuple = (1,2,3)
- #使用逆向收集,将my_tuple元组的元素传给nums参数
- foo('fkit' , *my_tuple)
- print("--------------------------")
- #使用逆向收集,将my_tuple元组的第一个元素传给name参数,剩下的元素传给nums参数
- foo(*my_tuple)
- print("--------------------------")
- #不使用逆向收集,my_tuple元组整体传给name参数
- foo(my_tuple)
- print("--------------------------")
- #字典使用逆向收集,会以关键字参数的形式传入
- def bar(book , price , desc):
- print(book , "这本书的价格是:" , price)
- print('描述的信息是:' , desc)
- my_dict = {'price': 89 , 'book': '《疯狂Python讲义》','desc' : '这是一本系统全面的Python学习图书。'}
- #按逆向收集的方式将my_dict的多个key-value对传给bar()函数
- bar(**my_dict)
'运行
——Python中函数的参数传递机制都是“值传递”。
值传递——就是将实际参数值的副本(复制品)传入函数,而参数本身不会受到任何影响。
例1:
- #*****************************
- #***程序名称:int_transfer_test.py
- #***程序功能:函数的参数传递机制
- # 值传递——就是将实际参数值得副本传入函数
- # 而参数本身不会受到任何影响
- #***编写日期:2019-5-18
- #*****************************
- def swap(a , b):
- #下面代码实现a,b变量的值交换
- a,b = b,a
- print("在swap函数里,a的值是:", a , "——b的值是:",b)
- a = 6
- b = 9
- swap(a ,b)
- print("交换结束后,变量a的值是:",a,"——b的值是:",b)
'运行
例2:
- #*****************************
- #***程序名称:dict_transfer_test.py
- #***程序功能:函数的参数传递机制
- # 参数本身是一个可变对象(例如列表、字典等)
- # 时,值得传递效果。
- #***编写日期:2019-5-18
- #*****************************
- def swap(dw):
- #下面代码实现dw的a,b两个元素的值交换
- dw['a'] , dw['b'] = dw['b'],dw['a']
- print("在swap函数里,a元素的值是:", dw['a'] , "——b元素的值是:",dw['b'])
- dw = {'a':6, 'b':9}
- swap(dw)
- print("交换结束后,a元素的值是:", dw['a'], "——b元素的值是:", dw['b'])
- '''执行代码的结果
- 在swap函数里,a元素的值是: 9 ——b元素的值是: 6
- 交换结束后,a元素的值是: 9 ——b元素的值是: 6
- '''
'运行
变量分为两种:
(1)局部变量:在函数中定义的变量(包括参数)。
(2)全局变量:在函数外面、全局范围内定义的变量。(可以在所有函数内被访问)
Python提供了三个工具函数来获取指定范围内的“变量字典”。
下面的代码示范了如何使用locals()、globals()函数访问局部范围和全局范围内的“变量字典”。
- #*****************************
- #***程序名称:locals_test.py
- #***程序功能:变量的作用域
- # 示范了如何使用locals()、globals()函数
- # 访问局部范围和全局范围内的“变量字典”。
- #***编写日期:2019-5-18
- #*****************************
- def test():
- age = 20
- #直接访问age局部变量
- print(age) #输出20
- #访问函数局部范围内的“变量数组”
- print(locals()) #{'age':20}
- #通过函数局部范围内的“变量数组”访问age变量
- print(locals()['age'])
- #通过locals()函数局部范围内的“变量数组”改变age变量的值
- locals()['age'] = 12
- #再次访问age变量的值
- print('xxx',age) #依然输出20
- #通过globals()函数修改x全局变量
- globals()['x'] = 19
- x = 5
- y = 20
- print(globals())
- #在全局范围内使用locals函数,访问的是全局变量的“变量数组”
- print(locals())
- #直接访问x全局变量
- print(x)
- #通过全局变量的“变量数组”访问x全局变量
- print(globals()['x'])
- #通过全局变量的“变量数组”对x全局变量赋值
- globals()['x'] = 39
- print(x)
- #在全局范围内使用locals函数对x全局变量赋值
- locals()['x'] = 99
- print(x)
'运行
Python语法规定:在函数内部对不存在的变量赋值时,默认就是重新定义新的局部变量。就会发生局部变量遮蔽全局变量的情形。
例如:
- #*****************************
- #***程序名称:globals_test.py
- #***程序功能:变量的作用域
- # 局部变量遮蔽全局变量
- #***编写日期:2019-5-18
- #*****************************
- name = 'Charlie'
- def test():
- #直接访问name全局变量
- #name = '孙悟空' #会报错
- print(name) #输出Charlie
- test()
- print(name) #输出Charlie
'运行
解决这问题有两种方式:
(1)访问被遮蔽的全局变量(通过globals()函数)
例如:
- #*****************************
- #***程序名称:globals_right1.py
- #***程序功能:变量的作用域
- # 访问被遮蔽全局变量
- #***编写日期:2019-5-18
- #*****************************
- name = 'Charlie'
- def test():
- #通过globals函数访问name全局变量
- print(globals()['name']) #输出Charlie
- name = '孙悟空'
- test()
- print(name) #输出Charlie
'运行
(2)在函数中声明全局变量
例如:
- #*****************************
- #***程序名称:globals_right2.py
- #***程序功能:变量的作用域
- # 在函数中声明全局变量
- #***编写日期:2019-5-18
- #*****************************
- name = 'Charlie'
- def test():
- #声明name是全局变量,后面的赋值语句不会重新定义局部变量
- global name
- #直接访问name全局变量
- print(name) #输出Charlie
- name = '孙悟空'
- test()
- print(name) #输出孙悟空
'运行
定义:被放在函数体内定义的函数,被称为局部函数。
(1)在默认情况下,局部函数对外部是隐藏的,只能在其封闭函数内有效,其封闭函数也可以返回局部函数,以便程序在其他作用域中使用局部函数。
例如:
- #*****************************
- #***程序名称:local_function.py
- #***程序功能:局部函数——被放在函数体内的函数
- #只能在其封闭的函数内有效,其封闭函数也可以返回局部函数,以便
- #在其他的作用域中使用局部函数。
- #***编写日期:2019-5-18
- #*****************************
- #定义函数,该函数会包含局部函数
- def get_math_func(type , nn):
- #定义一个计算平方的局部函数
- def square(n):
- return n * n
- #定义一个计算立方的局部函数
- def cube(n):
- return n * n * n
- #定义一个计算阶乘的局部函数
- def factorial(n):
- result = 1
- for index in range(2 , n + 1):
- result *= index
- return result
- #调用局部函数
- if type == "square" :
- return square(nn)
- elif type == "cube" :
- return cube(nn)
- else:
- return factorial(nn)
- print(get_math_func("square" , 3)) #输出9
- print(get_math_func("cube" , 3)) #输出27
- print(get_math_func("" , 3)) #输出6
'运行
(2)局部函数内的变量遮蔽它所在函数内的局部变量。可以通过nonlocal语句声明访问赋值语句。
例如:
- #*****************************
- #***程序名称:nonlocal_test.py
- #***程序功能:局部函数——通过nonlocal语句即可声明
- #访问赋值语句只是访问该函数所在函数内的局部变量
- #***编写日期:2019-5-18
- #*****************************
- def foo():
- #局部变量name
- name = 'Charlie'
- def bar():
- nonlocal name
- #访问bar()函数所在foo()函数内的name局部变量
- #赋值前name的值
- print(name) #Charlie
- name = '孙悟空'
- #赋值后name的值
- print(name)
- bar()
- foo()
'运行
函数本身也是一个对象,既可以赋值,也可作为其他函数的参数,还可以作为其他函数的返回值。
例如:
- #*****************************
- #***程序名称:function_var_test.py
- #***程序功能:函数的高级用法
- #***(1)把函数作为变量使用
- #***编写日期:2019-5-18
- #*****************************
- #定义一个计算乘方的函数
- def pow(base , exponent):
- result = 1
- for i in range(1,exponent + 1):
- result *= base
- return result
- #将pow函数赋值给my_fun,则my_fun可被当成pow使用
- my_fun = pow
- print(my_fun(3,4)) #输出81
- #定义一个计算面积的函数
- def area(width , height):
- return width * height
- #将area函数赋值给my_fun,则my_fun可被当成area使用
- my_fun = area
- print(my_fun(3,4)) #输出12
'运行
例如:
- #*****************************
- #***程序名称:function_param_test.py
- #***程序功能:函数的高级用法
- #***(2)把函数作为函数参数使用
- #***编写日期:2019-5-18
- #*****************************
- #定义函数类型的形参,其中fn是一个函数
- def map(data , fn):
- result = []
- #遍历data列表中的每个元素,并用fn函数对每个元素进行计算
- #然后将计算结果作为新数组的元素
- for e in data :
- result.append(fn(e))
- return result
- #定义一个计算平方的函数
- def square(n):
- return n * n
- #定义一个计算立方的函数
- def cube(n):
- return n * n * n
- #定义一个计算阶乘的函数
- def factorial(n):
- result = 1
- for index in range(2 , n + 1):
- result *= index
- return result
- data = [3,4,9,5,8]
- print("原数据:" , data)
- #下面程序代码调用map()函数三次,每次调用时传入不同的函数
- print("计算数组元素的平方")
- print(map(data,square))
- print("计算数组元素的立方")
- print(map(data,cube))
- print("计算数组元素的阶乘")
- print(map(data,factorial))
'运行
例如:
- #*****************************
- #***程序名称:function_return_test.py
- #***程序功能:函数的高级用法
- #***(3)把函数作为返回值
- #***编写日期:2019-5-18
- #*****************************
- def get_math_func(type):
- #定义一个计算平方的局部函数
- def square(n):
- return n * n
- #定义一个计算立方的局部函数
- def cube(n):
- return n * n * n
- #定义一个计算阶乘的局部函数
- def factorial(n):
- result = 1
- for index in range(2 , n + 1):
- result *= index
- return result
- #返回局部函数
- if type == "square" :
- return square
- if type == "cube" :
- return cube
- else:
- return factorial
- #调用get_math_func(),程序返回一个嵌套函数
- 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))
'运行
利用lambda表达式简化function_return_test.py。
代码如下:
- #*****************************
- #***程序名称:lambda_test.py
- #***程序功能:使用lambda表达式代替局部函数
- #***编写日期:2019-5-18
- #*****************************
- def get_math_func(type):
- result = 1
- #该函数返回的是lambda表达式
- if type == 'square':
- return lambda n: n * n
- elif type == 'cube' :
- return lambda n: n * n * n
- else:
- return lambda n: (1+n) * n / 2
-
- #调用get_math_func(),程序返回一个嵌套函数
- 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))
'运行
注意:lambda表达式只能是单行表达式,不允许使用更复杂的函数形式。其本质就是匿名的、单行函数体的函数。
lambda表达式的语法格式:
lambda [参数列表] : 表达式
两个用途:
(1)对于单行函数,使用lambda表达式可以省略去定义函数的过程,让代码更加简洁。
(2)对于不需要多次复用的函数,使用lambda表达式可以在用完之后立即释放,提高了性能。
例如:
- #*****************************
- #***程序名称:lambda_map.py
- #***程序功能:使用lambda表达式调用Python内置的map()函数
- #***编写日期:2019-5-18
- #*****************************
- #传入计算平方的lambda表达式作为参数
- x = map(lambda x: x*x , range(8))
- print([e for e in x]) #[0, 1, 4, 9, 16, 25, 36, 49]
- #传入计算平方的lambda表达式作为参数
- 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]
'运行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。