函数
函数
函数是组织好的,可重复使用,用来实现单一的、或相关联功能的代码段
函数能提高应用的模块性,和代码的重复利用率。python 中已经提供了很多的内建函数,如 print()。但是我们也可以自己创建函数,称之为自定义函数
1、定义函数
语法
def 函数名称(参数列表): 函数体
返回值
自定义一个简单的函数:
# /user/bin/env python __author__ = 'wenchong' def add_function(a,b): c = a+b return c
- def:表示函数的开始,在声明函数的时候必须以 def 开头,告诉计算机这里要声明一个函数,def 是 define 的简写
- 函数名称: 定义好函数之后,通过函数名称调用函数
- 函数体:函数中进行一系列的操作与算法,必须已冒号开始,并进行缩进
- 返回值:函数结束时选择性的返回一个对象给调用方
- 参数列表:为函数提供数据,必须放在圆括号里面
注:当一个程序中,出现重名函数时,函数是从上到下生效,并且会产生内存垃圾
2、函数的调用
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
如调用上面定义的简单函数:
result = add_function(1,2)
3、返回值
函数的返回值就是函数像调用方返回的对象
返回值使用 return object,object 可以是任何对象
以上面定义的简单函数为例,通过 return c 将变量 c 返回给调用方,调用方即可通过一个变量捕获函数的返回
result = add_function(1,2) print(result) 输出结果: 3
上面的函数明确了返回值 return c,当一个函数中没有明确 return object 时,默认返回 None
def add_function(a,b): c = a+b print('a+b=',c) result = add_function(3,4) print('result=',result)
输出结果: a+b= 7 result= None
当函数中只有 return,但是没有 object时,默认返回 None
4、参数
形参:在定义函数时,圆括号里面的变量称之为形参
实参:在调用函数时,圆括号里面传递的参数称之为实参
参数的类型分为:必需参数[普通参数],关键字参数,默认参数,动态参数
必需参数[普通参数]
必需参数须已正确的顺序传入参数,调用的数量必需与声明的数量一样
如上面的例子,a,b 即为必需参数,当传入的参数与声明的数量一致时,执行函数体,如不一致会报错。
# 调用函数 result = add_function(1) # 返回报错信息 Traceback (most recent call last): File "test.py", line 23, in <module> result = add_function(1) TypeError: add_function() missing 1 required positional argument: 'b'
关键字参数
在必需参数中,传入的参数必须和声明的参数顺序一致,而关键字参数即可允许函数调用时的参数顺序和声明时的顺序不一致,因为 Python 解释器用参数名匹配参数值
# 定义函数 def userinfo(username,age): """ 输出用户的名称与年龄 """ print("姓名:",username) print("年龄:",age) # 调用函数,参数顺序和声明的顺序不一致 userinfo(age=8,username="WenChong")
输出结果:
姓名: WenChong
年龄: 8
默认参数
当函数调用时,有些参数 99% 的调用都是同一个值,当我们在调用这个函数的时候,就可以用到默认参数,只有当参数需要传递的值不为默认值时,我们再传入参数。
默认参数必须在位置参数之后
# 定义一个函数,age=8 def userinfo(username,age=8): """ 输出用户的名称与年龄 """ print("姓名:",username) print("年龄:",age) # 调用函数时,未传入 age 参数 userinfo(username="WenChong") 输出结果: 姓名: WenChong 年龄: 8
根据上面的实例,当 age 不等于 8 时,调用方式如下:
# 调用函数,指定 age=10 userinfo(username="WenChong",age=10) # 输出结果 姓名: WenChong 年龄: 10
动态参数
在位置参数时,当传递的参数小于或大于声明的参数,则会出现报错,为了使调用时不报错,这里就需要使用到动态参数。
动态参数有两种,可以只使用其中一种,或两种一起使用
*args: 一个 * 开头,后面跟变量名,建议使用 args[潜规则],已元组的方式接收多出的位置参数
**kwargs: 两个 ** 开头,后面跟变量名,建议使用 kwargs[潜规则],已字典的方式接受多出的关键字参数
# 定义一个函数,该函数可以接受不定长的参数 def userinfo(username,*args,**kwargs): """ 输出用户信息 """ print("姓名:",username) print("其他信息1:",args) print("其他信息2:",kwargs) # 调用函数,由于定义的函数有一个位置参数,所以参数必须大于等于一个 print('传递 1 个参数'.center(30,'-')) userinfo("WenChong") print('传递 3 个参数'.center(30,'-')) userinfo("WenChong",10,"male") print('传递 3 个参数,以及关键字参数'.center(30,'-')) userinfo('WenChong',10,'male',job='IT',k1='v1',k2='v2')
输出结果:
-----------传递 1 个参数----------- 姓名: WenChong 其他信息1: () 其他信息2: {} -----------传递 3 个参数----------- 姓名: WenChong 其他信息1: (10, 'male') 其他信息2: {} -------传递 3 个参数,以及关键字参数------- 姓名: WenChong 其他信息1: (10, 'male') 其他信息2: {'job': 'IT', 'k1': 'v1', 'k2': 'v2'}
可以通过 * 或 ** 捕获参数,也可以通过 * 或 ** 传递参数
# 定义一个函数, def userinfo(username,age,job): """ 输出用户的名称与年龄 """ print("姓名:",username) print("年龄:",age) print("工作:",job) # 调用函数,由于定义的函数有一个位置参数,所以参数必须大于等于一个 print('普通传递'.center(30,'-')) userinfo("WenChong",10,'IT') print('通过 * 传递'.center(30,'-')) info = ['WenChong',10,"male"] userinfo(*info) print('通过 ** 传递'.center(30,'-')) info = {'username':'WenChong','age':10,'job':'IT'} userinfo(**info)
输出结果:
-------------普通传递------------- 姓名: WenChong 年龄: 10 工作: IT -----------通过 * 传递------------ 姓名: WenChong 年龄: 10 工作: male -----------通过 ** 传递----------- 姓名: WenChong 年龄: 10 工作: IT
按值传递参数和按引用传递参数
在 Python 中,所有参数(变量)都是按引用传递。如果你在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。
def changeme( mylist ): "修改传入的列表" mylist.append([1,2,3,4]) print("函数内取值: ", mylist) # 调用函数 mylist = ['WenChong'] changeme(mylist) print('函数外取值: ',mylist)
输出结果:
函数内取值: ['WenChong', [1, 2, 3, 4]] 函数外取值: ['WenChong', [1, 2, 3, 4]]
5、函数的文档
在函数的名称下面输入函数的说明文档。一般以三个双引号包裹。
通过 help() 内置函数可以查看函数的说明文档,或通过 foo.__doc__ 查看
def foo(): """ This is a test function. """ pass # 查看帮助信息 print('help()'.center(30,'-')) help(foo) print('__doc__'.center(30,'-')) print(foo.__doc__) # 输出结果: ------------help()------------ Help on function foo in module __main__: foo() This is a test function. -----------__doc__------------ This is a test function.
6、变量的作用域
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。
total = 0; # 这是一个全局变量 # 可写函数说明 def sum( arg1, arg2 ): #返回2个参数的和." total = arg1 + arg2 # total在这里是局部变量. print ("函数内是局部变量 : ", total) return total #调用sum函数 sum( 10, 20 ) print ("函数外是全局变量 : ", total) # 输出结果 函数内是局部变量 : 30 函数外是全局变量 : 0
当全局变量为可变数据类型,如字典,列表,set 时,在函数内只能对其进行修改,不能进行重新赋值
# 定义一个全局变量 mylist = [1,2,3] # 定义一个修改全局变量的函数 def foo(): mylist.append(4) # 调用函数 foo() # 输出全局变量 print(my list) # 输出结果 [1, 2, 3, 4]
# 定义全局变量 mylist = [1,2,3] def foo(): mylist = [1] # 重复赋值 foo() print(my list) # 输出结果 [1,2,3]
当需要在函数内为全局变量重新赋值时,需要使用 global。
total = 0; # 这是一个全局变量 # 可写函数说明 def sum( arg1, arg2 ): #返回2个参数的和." global total # 将局部变量声明为全局变量 total = arg1 + arg2 # total在这里是局部变量. print ("函数内是局部变量 : ", total) return total #调用sum函数 sum( 10, 20 ) print ("函数外是全局变量 : ", total) # 输出结果 函数内是局部变量 : 30 函数外是全局变量 : 30
匿名函数
python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效
语法
lambda [arg1 [,arg2,.....argn]]:expression
实例
sum = lambda arg1, arg2: arg1 + arg2
# 定义函数 sum = lambda arg1, arg2: arg1 + arg2 # 调用函数 print ("相加后的值为 : ", sum( 10, 20 ))
其他补充信息
三元运算
# 当 1 == 1 时,name 的值为 wenchong,否则为 WenChong name = “wenchong” if 1 == 1 else “WenChong”
format 格式化字符串
# 类似位置参数 s1 = “i am {0} ,age {1}”.format(“wenchong”,18) # 类似关键字参数 s3 = “i am {name} ,age {age}”.format(name=“wenchong”,age=18) # 类似动态参数 s3 = “i am {0} ,age {1}”.format(*[“wenchong”,18]) s4 = “i am {name} ,age {age}”.format(**{name:“wenchong”,age:18}) # 输出结果均为: i am wenchong, age 18