10.【Python编程】函数的定义、调用、参数传递及其应用
10.1 函数的定义与调用
数学上的定义编程上的定义 10.2 参数及参数传递
python 传不可变对象实例python 传可变对象实例参数类型 10.3 lambda表达式创建匿名函数
10.【Python编程】函数的定义、调用、参数传递及其应用备注: 本教程主要使用Python3.6在jupyter notebook上编程实现。Python环境配置参考《【Python学习】Windows10开始你的Anaconda安装与Python环境管理》或者《【Python学习】纯终端命令开始你的Anaconda安装与Python环境管理》。
10.1 函数的定义与调用 数学上的定义在数学上,函数被定义为:给定一个数集A,假设其中的元素为x,对A中的元素x施加对应法则f,记作f(x),得到另一数集B,假设B中的元素为y,则y与x之间的等量关系可以用y=f(x)表示。
函数概念含有三个要素:定义域A、值域B和对应法则f。其中核心是对应法则f,它是函数关系的本质特征。
在我们初中、高中当中,出现的一元一次函数、一元二次函数、三角函数、指数函数、对数函数,便是如此。
而在计算机科学里面,函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。
无论是数学上还是计算机科学上,函数都包含了输入(自变量)、处理代码(处理法则)、输出(因变量)。
在python当中,你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。函数内容以冒号 : 起始,并且缩进。return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
它的格式为:
def 函数名(参数列表): 函数体 return 返回结果
例如:
使用python实现数学上的一元函数
# y = 2x+1 def f1(x): y = 2*x + 1 return y # 尝试使用该函数计算当x=5时的y值: print("f1(5)=", f1(5)) # 调用f1函数
f1(5)= 11
使用python实现数学上的一元二次函数
# y=2x^2+3x-9 def f2(x): y=2*x**2+3*x-9 return y # 尝试使用该函数计算当x=5时的y值: print("f2(5)=", f2(5)) # 调用f2函数
f2(5)= 56
使用python实现输入半径计算圆的面积、圆的周长
import math # 计算圆的面积 def cal_area_of_circle(r): s = math.pi*r*r return s # 计算圆的周长 def cal_circumference_of_circle(r): c = 2*math.pi*r return c # 测试函数 r = float(input("请输入圆的半径(cm):")) print("圆的半径是:", r) print("圆的面积是:", cal_area_of_circle(r)) print("圆的周长是:", cal_circumference_of_circle(r))
请输入圆的半径(cm):5 圆的半径是: 5.0 圆的面积是: 78.53981633974483 圆的周长是: 31.4159265358979310.2 参数及参数传递
在python当中,函数的参数,严格来说,是没有类型的,也就是,可以传给函数的参数任意类型的对象。通常可以约束要求传入的对象的类型,或者在函数内部判断对象的类型。
在 python 中,类型属于对象,变量是没有类型的。Python3 的六个标准数据类型中:
不可变类型(3 个):Number(数字)、String(字符串)、Tuple(元组)可变类型(3 个):List(列表)、Dictionary(字典)、Set(集合)
解释:python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
python 传不可变对象实例不可变类型:类似于 C++ 的值传递,变量赋值 x=5 后再赋值 x=10,这里实际是新生成一个 int 值对象 10,再让 x 指向它,而 5 被丢弃,不是改变 x 的值,相当于新生成了 x。
在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的 id。
# 验证不可变类型变量的赋值 x = 5 id1 = id(x) print(id1) x = 10 id2 = id(x) print(id2) print(id1 == id2)
94347800181568 94347800181728 False
# python传不可变对象,在函数内修改,并不会影响函数外的对象值 def change(x): # 函数内部的符号x表示形参 print("函数内部的形参x的id=", id(x)) # 形参和实参指向的是同一个对象 x=2022 print("函数内部重新赋值后的形参x的id=", id(x)) # 形参指向一个新的对象 print("-----------当x为数字类型时------------------") x=2021 print("x的类型为:",type(x)) print("实参x的取值=", x) print("传入函数的实参x的id=", id(x)) change(x) print("实参x的取值=", x)
-----------当x为数字类型时------------------ x的类型为:python 传可变对象实例实参x的取值= 2021 传入函数的实参x的id= 140642597090288 函数内部的形参x的id= 140642597090288 函数内部重新赋值后的形参x的id= 140642597089840 实参x的取值= 2021
可变类型:类似于 C++ 的引用传递,变量赋值 list1=[1,2,3,4] 后再赋值 list1[2]=5 则是将 list1 的第三个元素值更改,本身list1没有动,只是其内部的一部分值被修改了。
# 验证可变类型变量的赋值 list1=[1,2,3,4] id3 = id(list1) print(id3) list1[2] = 5 id4 = id(list1) print(id4) print(id3 == id4)
140642597025800 140642597025800 True
# python传可变对象,在函数内修改,会影响函数外的对象值 def change(x): # 函数内部的符号x表示形参 print("函数内部的形参x的id=", id(x)) # 形参和实参指向的是同一个对象 x.append(2022) # 传入函数的和在列表末尾添加新内容的对象用的是同一个引用。 print("函数内部修改列表后的形参x的id=", id(x)) # 形参指向一个新的对象 print("-----------当x为列表类型时------------------") x=[2019,2020,2021] print("x的类型为:",type(x)) print("实参x的取值=", x) print("传入函数的实参x的id=", id(x)) change(x) print("实参x的取值=", x)
-----------当x为列表类型时------------------ x的类型为:参数类型实参x的取值= [2019, 2020, 2021] 传入函数的实参x的id= 140642614321416 函数内部的形参x的id= 140642614321416 函数内部修改列表后的形参x的id= 140642614321416 实参x的取值= [2019, 2020, 2021, 2022]
以下是调用函数时可使用的正式参数类型:
必需参数:必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。关键字参数:函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。默认参数:调用函数时,如果没有传递参数,则会使用默认参数。不定长参数:你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,声明时不会命名。加了星号 *的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
def functionname([formal_args,] *var_args_tuple ): "函数_文档字符串" function_suite return [expression]
加了两个星号 ** 的参数会以字典的形式导入。
def functionname([formal_args,] **var_args_dict ): "函数_文档字符串" function_suite return [expression]
声明函数时,参数中星号 *可以单独出现,如果单独出现星号 * 后的参数必须用关键字传入。
# 下面的例子的r就是必需参数 def cal_area_of_circle(r): s = math.pi*r*r return s # 下面的例子的a,b就是必需参数 def cal_area(a,b): '''计算矩阵的面积 ''' s = a*b return s
print(cal_area(1,3)) #print(cal_area(1)) ''' 执行cal_area(1) 报错:TypeError: cal_area() missing 1 required positional argument: 'b' ''' # 下面的形式为关键字参数,函数调用使用关键字参数来确定传入的参数值。 print(cal_area(a=1,b=3)) print(cal_area(b=3,a=3))
3 3 9
# 下面的例子的a,b指定了默认参数 def cal_area_v2(a=7,b=8): '''计算矩阵的面积 ''' s = a*b return s # 实例中如果没有传入a、b参数,就使用默认参数 print(cal_area_v2()) print(cal_area_v2(3)) print(cal_area_v2(5)) print(cal_area_v2(b=3))
56 24 40 21
# 下面的例子为不定长参数 def printinfo(exp_name, *vartuple): "打印任何传入的参数" print("输出: ") print(exp_name) print(vartuple) printinfo('exp1', [1,2,3,4], 50,"Hello world!")
输出: exp1 ([1, 2, 3, 4], 50, 'Hello world!')
# 下面的例子为不定长参数 def printinfo( arg1, **vardict ): "打印任何传入的参数" print("输出: ") print(arg1) print(vardict) # 调用printinfo 函数 printinfo(1,a=2,b=3)
输出: 1 {'a': 2, 'b': 3}
def f(a,b,*,c): return a*b*c print(f(1,2,c=3)) # 正确调用方式 #print(f(1,2,3)) ''' print(f(1,2,3)) 报错:TypeError: f() takes 2 positional arguments but 3 were given '''
6 'nprint(f(1,2,3))n报错:TypeError: f() takes 2 positional arguments but 3 were givenn'10.3 lambda表达式创建匿名函数
所谓匿名,也就是不再使用def语句这样标准的形式定义一个函数。它的格式为:
lambda [arg1 [,arg2,.....argn]]:expression
说明:
lambda只是一个表达式,函数体比 def 简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
lambda函数的应用场景:
将lambda函数赋值给一个变量,通过这个变量间接调用该lambda函数。将lambda函数赋值给其他函数,从而将其他函数用该lambda函数替换。将lambda函数作为参数传递给其他函数。部分Python内置函数接受函数作为参数,典型的此类内置函数有这些:filter函数、sorted函数、map函数、reduce函数。
# lambda能将函数描述简化为一行代码 def f(x): return x**2 print(f(4)) g = lambda x:x**2 print(g(4))
16 16
# 将列表按照其绝对值大小升序排序 list1 = [9,-2,6,-5] list2 = sorted(list1,key=lambda x:abs(x)) print(list2)
[-2, -5, 6, 9]
# 过滤掉列表中的偶数值 list3 = [1,2,3,4,5,6,7,8,9] list4 = [i for i in filter(lambda x: x % 2 == 0, list3)] print(list4)
[2, 4, 6, 8]
# 将列表中的元素加1 list5 = [1,2,3,4,5] list6 = [i for i in map(lambda x: x+1, list5)] print(list6)
[2, 3, 4, 5, 6]
# 将匿名函数保存在字典的value位置上 func_dict={'2':(lambda x: x * 2), '3':(lambda x: x * 3), '4':(lambda x: x * 4) } print(func_dict["2"](3)) # 计算3的2次方 print(func_dict["3"](3)) # 计算3的3次方
6 9
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)