函数
设计一个程序:
期待结果:
*
***
*****
*******
*********
***********
*********
*******
*****
***
*
*
***
*****
*******
*********
***********
*********
*******
*****
***
*
如果没有函数,我们的实现方式:
# 打印一个菱形
rows=6
i=j=k=1
#菱形的上半部分
for i in range(rows):
for j in range(rows-i):
print(" ",end=" ")
j+=1
for k in range(2*i-1):
print("*",end=" ")
k+=1
print("\n")
#菱形的下半部分
for i in range(rows):
for j in range(i):
print(" ",end=" ")
j+=1
for k in range(2*(rows-i)-1):
print("*",end=" ")
k+=1
print("\n")
-
相信大家一定看出来了,这种方式会出现大量重复代码,对于阅读和维护整个程序都会变得十分麻烦。
-
这时候,函数就出现了!
-
简单说,函数就是一段封装好的,可以重复使用的代码,它使得我们的程序更加模块化,避免大量重复的代码。
-
刚才的程序函数版本:
def print_ling():
rows=6
i=j=k=1
#菱形的上半部分
for i in range(rows):
for j in range(rows-i):
print(" ",end=" ")
j+=1
for k in range(2*i-1):
print("*",end=" ")
k+=1
print("\n")
#菱形的下半部分
for i in range(rows):
for j in range(i):
print(" ",end=" ")
j+=1
for k in range(2*(rows-i)-1):
print("*",end=" ")
k+=1
print("\n")
print_ling()
print_ling()
7.1、函数声明
- 声明一个函数,也就是创建一个函数,可以理解为将一段可以重复使用的代码通过关键字def包裹起来。具体的语法格式如下:
'''
def 函数名(参数列表):
'''
# 函数文档
params:
return:
'''
# 实现特定功能的多行代码
[return [返回值]]
'''
- 其中,用 [] 括起来的为可选择部分,即可以使用,也可以省略。
- 此格式中,各部分参数的含义如下:
- 函数名:一个符合 Python 语法的标识符,最好见名知意,多个单词可以使用
_
表示,比如cal_sum
- 形参列表:设置该函数可以接收多少个参数,多个参数之间用逗号( , )分隔。
- [return [返回值] ]:整体作为函数的可选参参数,用于设置该函数的返回值。
- python的函数体是通过冒号+缩进声明的
def foo():
print("foo函数")
7.2、函数调用
-
函数的声明并没有执行函数中的代码块,想要执行函数体,需要进行函数调用,一个函数可以调用多次。
-
函数调用语法:
# 函数名() # 不考虑参数和返回值的调用
def foo():
print("foo函数")
foo()
debug模式运行:
# 函数的声明
def bar():
print("bar1")
print("bar2")
print("bar3")
# 函数的声明
def foo():
print("foo1")
print("foo2")
print("foo3")
# 函数调用
foo()
# 函数调用
bar()
# 函数调用
foo()
7.3、函数参数
- 像上面我们举的例子,我想打印一个八层菱形和六层菱形,怎么设计?
7.3.1、形参和实参
- 声明一个计算1-100和的函数
def cal_sum():
ret = 0
for i in range(1,101):
ret+=i
print(ret)
- 但是问题来了,如果我想计算1-200的和怎么呢,再声明一个新的函数吗?
- 明显我们会发现计算1-100和与计算1-200的和逻辑是相同的,只有一个动态变化值,
- 所以我们引入了参数的概念,这样可以使函数的功能更加强大灵活:
# 案例1
def cal_sum(temp): # temp就是引入的函数形式参数
ret = 0
for i in range(1,temp+1):
ret+=i
print(ret)
cal_sum(100) # 每次调用可以根据需要传入需要的值,这个具体的值成为实际参数简称实参。
cal_sum(101)
# 案例2
def add():
x = 10
y = 20
print(x+y)
def add(x, y): # 声明的参数称之为形式参数,简称形参
print(x + y)
# 调用add函数 # 将调用过程中传入的值称之为实际参数,简称实参
add(5, 6) # 将5赋值给x,将6赋值给了y ,函数体将x+y,即5+6计算出来,打印
# 调用add函数
add(10, 5) # 将10赋值给x,将6赋值给了5 ,函数体将x+y,即10+5计算出来,打印
-
在函数的定义阶段 括号内写的变量名,叫做该函数的形式参数,简称形参。
- 在函数的调用阶段,括号内实际传入的值,叫做实际参数,简称实参。
- 该例中,temp就是的函数形式参数,而每次调用根据需要传入的值,比如100,101都是实参。
-
形参就相当于变量名,而实参就相当于变量的值,函数调用传参的过程 就是给形参变量名赋值的过程。
-
函数参数只有在函数调用阶段有效,函数运行结束,参数作为垃圾释放。
7.3.2、位置参数
- 位置参数,有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中,
- 换句话说,调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。
# 例1
def add(x,y): # x,y是形参,用来接收实参
print(x+y)
add(2,3) # 2,3 是实际参数,分别传递给形参x,y
# 例2
def add(x,y,z):
print(x+y)
add(2,3) # 缺少一个实际参数传递给z
# 例3
def add(x,y):
print(x+y)
add(2,3,4) # 缺少一个形式参数接收给z
7.3.3、默认参数
- Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。
- 这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。
def print_stu_info(name,age,gender="male"):
print("学员姓名:",name)
print("学员年龄:",age)
print("学员性别:",gender)
print_stu_info("张三",23)
当定义一个有默认值参数的函数时,有默认值的参数必须位于所有没默认值参数的后面,否则报错!
7.3.4、关键字参数
- 关键字参数可以避免牢记参数位置的麻烦,令函数的调用和参数传递更加灵活方便。
- 关键字参数是指使用形式参数的名字来确定输入的参数值。
- 通过此方式指定函数实参时,不再需要与形参的位置完全一致,只要将参数名写正确即可。
def print_stu_info(name,age,height,weight,job):
print("学员姓名:",name)
print("学员年龄:",age)
print("学员身高:",height)
print("学员体重:",weight)
print("学员工作:",job)
print_stu_info("张三",23,"180cm","80kg","销售")
print_stu_info(name="张三",height="180cm",weight="90kg",job="销售",age=23)
print_stu_info("张三",height="180cm",weight="90kg",job="销售",age=23)
使用位置参数和关键字参数混合传参的方式。但需要注意,混合传参时关键字参数必须位于所有的位置参数之后。
7.3.5、不定长参数
- 在函数定义中使用
*args
和**kwargs
传递可变长参数。*args
用作传递非命名键值可变长参数列表(位置参数);**kwargs
用作传递键值可变长参数列表。*args
的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。**kwargs
的参数会以字典的形式导入。
# *args
def add(*args):
print(args)
print(type(args))
ret = 0
for i in args:
ret += i
print(ret)
add(12,23,45)
# **kwargs
def print_stu_info(**kwargs,):
print(kwargs)
print_stu_info(name="张三",height=190)
同时使用*args
和**kwargs
:
def print_stu_info(name, age=18, *args, **kwargs):
print(name, age)
print(args)
print(kwargs)
print_stu_info("dream", 20, "China", "Beijing", height="188cm", weight="60kg")
注意点:
1、参数
arg
、*args
、**kwargs
三个参数的位置必须是一定的。必须是(arg,*args,**kwargs)
这个顺序,否则程序会报错。2、不定长参数的长度可以为零。
3、
args
和kwargs
其实只是编程人员约定的变量名字,args
是 arguments 的缩写,表示位置参数;kwargs
是 keyword arguments 的缩写,表示关键字参数。
7.4、函数返回值
- 到目前为止,我们创建的函数都只是对传入的数据进行了处理,处理完了就结束。
- 但实际上,在更多场景中,我们还需函数将处理的结果反馈回来。
- 通过关键字return语句可以返回任意类型的数值。
7.4.1、基本使用
def add(x,y):
return x+y # return是函数的终止语句
ret = add(2,3)
print(ret)
7.4.2、默认返回值
- 在 Python 中,有一个特殊的常量 None(N 必须大写)。
- 和 False 不同,它不表示 0,也不表示空字符串,而表示没有值,也就是空值。
- None 是
NoneType
数据类型的唯一值(其他编程语言可能称这个值为 null、nil 或 undefined),也就是说,我们不能再创建其它NoneType
类型的变量,但是可以将 None 赋值给任何变量。
- Python一个函数中如果没有return语句或者return后没有具体值,都默认返回None,比如print()函数就没有返回。
7.4.3、返回多个值
- return也可以返回多个值,python其实会将多个值放在一个元组中元组返回。
def login(user,pwd):
flag = False
if user == 'dream' and pwd == 123:
flag = True
return flag,user
# ret = login("dream",123)
flag,user = login("dream",123)
if flag:
print("{}登陆成功!".format(user))
else:
print("用户名或者密码错误!")
7.5、函数嵌套
def foo():
def bar():
print("bar功能")
print("foo功能")
foo()