为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数。
1 函数定义和调用
定义函数的格式:
def 函数名():
代码
调用函数:函数名()
注:函数可以嵌套调用。
举例:
def sumab(a, b):
"求和" # 函数的功能说明
x = a + b
return x
x = 1
y = 2
z = sumab(x, y)
print('%d和%d的和为:%d'%(x, y, z))
函数的参数:
定义时小括号中的参数,用来接收参数用的,称为 “形参”;
调用时小括号中的参数,用来传递给函数用的,称为 “实参”。
函数的返回值:
所谓“返回值”,就是程序中函数完成一件事情后,最后给调用者的结果。
举例:
def divide(a, b):
shang = a//b
yushu = a%b
return shang, yushu
sh, yu = divide(7, 2)
print('商:%d 余数:%d'%(sh, yu))
运行结果:
商:3 余数:1
函数返回多个值,本质是利用了元组。
2 4种函数的类型
定义函数时,是根据实际的功能需求来设计的。
函数的类型 | 用处 |
无参数,无返回值 | 打印提示等 |
无参数,有返回值 | 采集数据等 |
有参数,无返回值 | 对某些变量设置数据而不需结果时使用 |
有参数,有返回值 | 数据处理并需要结果等 |
3 局部变量和全局变量
3.1 局部变量
就是在函数内部定义的变量。
不同的函数,可以定义相同的名字的局部变量,但是不会产生影响。
局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用。
3.2 全局变量
函数外边定义的变量,能够在所有的函数中进行访问。
如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,小技巧:强龙不压地头蛇。
注:
(1)函数中可以直接引用全局变量,但是如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错。
(2)全局变量命名一般用全部大写。
比如:
AA = 1
def test1():
global AA
AA += 1
return AA
def test2(AA):
AA += 1
return AA
def test3():
a = AA
a += 1
return a
print('修改前的AA:%d'%AA)
print('test1()后的AA:%d'%test1())
print('test2()后的AA:%d'%test2(AA))
print('test3()后的AA:%d'%test3())
运行结果:
修改前的AA:1
test1()后的AA:2
test2()后的AA:2
3.3 可变类型的全局变量
在函数中,不使用global声明全局变量时不能修改全局变量的本质是 不能修改全局变量的指向,即不能将全局变量指向新的数据。
对于不可变类型的全局变量来说,因其指向的数据不能修改,所以不使用global时无法修改全局变量。
对于可变类型的全局变量来说,因其指向的数据可以修改,所以不使用global时也可修改全局变量。
举例:
list = [1,]
def test1():
"测试程序1" # 函数的功能说明
list.append(1)
return list
print('修改前的list:', list)
test1()
print('test1()后的bist:', list)
运行结果:
修改前的list: [1]
test1()后的bist: [1, 1]
4 函数参数2
4.1 缺省参数
函数时,缺省参数的值如果没有传入,则被认为是默认值。
注:带有默认值的参数一定要位于参数列表的最后面。
举例:
def printinfo(name, age = 18):
# 打印任何传入的字符串
print("Name: ", name)
print("Age ", age)
# 调用printinfo函数
printinfo(name="zhao" )
printinfo(age=9, name="qian" )
运行结果:
Name: zhao
Age 18
Name: qian
Age 9
4.2 不定长参数
有时可能需要一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数,声明时不会命名。
基本语法如下:
def functionname(formal_args, *args, **kwargs):
"函数_文档"
function_suite
return [expression]
加了星号(*)的变量args(*args)会存放所有未命名的变量参数,args为元组;而加**的变量kwargs(**kwargs)会存放命名参数,即形如key=value的参数, kwargs为字典。
def fun(a, b, *args, **kwargs):
"""可变参数演示示例"""
print("a =", a)
print("b =", b)
print("args =", args)
print("kwargs: ")
for key, value in kwargs.items():
print(key, "=", value)
fun(1, 2, 3, 4, m=5, n=6) # 注意传递的参数对应
运行结果:
a = 1
b = 2
args = (3, 4)
kwargs:
m = 5
n = 6
4.3 引用传参
python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,所以运算不会影响到变量自身;而对于可变类型来说,函数体中的运算有可能会更改传入的参数变量。
区分:a+=a 和 a=a+a。
示例1(a+=a):
def selfadd1(a):
"函数_文档字符串"
a += a # a = a + a # 注意区分a+=a和a=a+a的区别
# return a
x = 1
y = [1,2]
add1 = selfadd1(x)
add2 = selfadd1(y)
print(x)
print(y)
运行结果:
1
[1, 2, 1, 2]
示例1(a+=a)会改变引用参数的值。
示例2(a=a+a):
def selfadd1(a):
"函数_文档字符串"
a = a + a # a += a # 注意区分a+=a和a=a+a的区别
# return a
x = 1
y = [1,2]
add1 = selfadd1(x)
add2 = selfadd1(y)
print(x)
print(y)
运行结果:
1
[1, 2]
示例2(a=a+a)不会改变引用参数的值。
示例3(a+a):
a = [1,2]
print(a+a)
运行结果:
[1, 2, 1, 2]
可以用id()来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标示。
示例:
a = [1,2]
b = a
a.append(3)
d = 1
e = d
d = 2
print(a, b)
print(id(a), id(b)) # a,b是同一个id值
print(d, e)
print(id(d), id(e)) # d,e是不同的id值
运行结果:
[1, 2, 3] [1, 2, 3]
1881014607680 1881014607680
2 1
1880962984272 1880962984240
可变类型,值可以改变:列表 list、字典 dict。
不可变类型,值不可以改变:数值类型 int, long, bool, float、字符串 str、元组 tuple。
5 递归函数和匿名函数
递归函数:
如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数。
匿名函数:
lambda关键词能创建小型匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
lambda函数的语法只包含一个语句,如下:
lambda arg1, arg2, ...., argn:expression
举例:
lambda函数能接收任何数量的参数但只能返回一个表达式的值。
匿名函数不能直接调用print,因为lambda需要一个表达式
匿名函数的应用场合:
1、自定义函数
def fun(a, b, opt):
print("a =", a)
print("b =", b)
print("result =", opt(a, b))
fun(1, 2, lambda x,y:x+y)
a = 1
b = 2
2、作为内置函数的参数
stus = [
{"name":"zhangsan", "age":18},
{"name":"lisi", "age":19},
{"name":"wangwu", "age":17}
]
# 按照name排序:
stus.sort(key = lambda x:x['name'])
print(stus)
# 按照age排序:
stus.sort(key = lambda x:x['age'])
print(stus)
运行结果:
[{'name': 'lisi', 'age': 19}, {'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}]
[{'name': 'wangwu', 'age': 17}, {'name': 'zhangsan', 'age': 18}, {'name': 'lisi', 'age': 19}]
6 函数使用注意事项
(1)自定义函数
一个函数到底有没有返回值,就看有没有return,因为只有return才可以返回数据;
函数中,可以有多个return语句,但是只要执行到一个return语句,那么就意味着这个函数的调用完成。
在调用函数时,参数列表中变量的个数根据实际传递的数据的多少来确定。
函数名不能重复。
(2)调用函数
如果调用的函数在定义时有形参,那么在调用的时候就应该传递参数。
调用时,实参的个数和先后顺序应该和定义函数中要求的一致。
如果调用的函数有返回值,那么就可以用一个变量来进行保存这个值。
(3)作用域
在一个函数中定义的变量,只能在本函数中用(局部变量);
在函数外定义的变量,可以在所有的函数中使用(全局变量)。
参考:
Python官方文档:https://docs.python.org/3/library/
https://blog.csdn.net/swan777/article/details/89040802