1.函数的介绍
为什么要有函数?因为在平时写代码时,如果没有函数的话,那么将会出现很多重复的代码,这样代码重用率就比较低。。。并且这样的代码维护起来也是很有难度的,为了解决这些问题,就出现了函数,用来将一些经常出现的代码进行封装,这样就可以在任何需要调用这段代码的地方调用这个函数就行了。
函数的定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
代码重用
保持一致性
可扩展性
2.函数的创建
在python中函数定义的格式如下:
def 函数名(形参): 函数体内部代码块
函数的调用使用 函数名(实参) 就可以调用函数了。
函数名的命名规则和变量的命名规则一样:
- 函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
- 函数名是区分大小写的。
- 函数名不能是保留字。
形参和实参的区别:
函数在定义的时候,函数名后面的括号中可以添加参数,这些参数就叫做形参,形参:顾名思义就是形式参数,只是一个代号。
实参是在调用函数的时候函数名后面的括号中的参数,形参和实参需要一一对应起来,否则调用函数会报错。
3.函数参数及返回值
前面提到函数的形参和实参要一一对应,那么参数对应有如下几种:
- 必须参数
- 关键字参数
- 默认参数
- 不定长参数 *args
- 不定长参数 **kwargs
1.必须参数:
必须参数必须以对应的关系一个一个传递进入函数,函数调用时传递的实参必须和函数定义时的形参一一对应,不能多也不能少,顺序也得一致。
举个栗子:
def f(name, age):
print(name, age)
f("小明", 18) # 运行结果: 小明 18
2.关键字参数
关键字参数是实参里面的概念,在调用函数的时候声明某个参数是属于某个关键字的。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
举个栗子:
def f(name, age):
print(name, age)
# 使用关键字参数可以不在意参数的位置顺序
f(age=18, name="小明") # 运行结果: 小明 18
# 如果不是所有参数都是关键字传参,那么位置参数必须挡在关键字传参前边,否则会报错
f("小李", age=19) # 运行结果: 小李 19
f(name="小白", 20) # 运行结果:SyntaxError: positional argument follows keyword argument
3.默认参数
默认参数是在函数声明的时候,可以给某个参数指定默认值,这样的参数叫做默认值参数。如果在调用函数的时候,默认参数没有接收到对应的实参,那么就会将默认值赋值给这个参数。
举个栗子:
def f(name, age, sex="male"):
print(name, age, sex)
f("小黑", 18) # 运行结果: 小黑 18 male
这样,就会把默认参数male赋值给sex了。
4.不定长参数 *args
在python里面,函数在声明的时候,参数中可以使用(*变量名)的方式来接受不确定长度的参数,但是在python里面大家约定俗成使用*args接受不定长参数,这样在调用函数的时候传递的参数就可以是不定长度的了。args接受了不定长参数之后,将这些参数放到一个tuple里面,可以通过访问args来获取这些不定长参数。
举个栗子:
def f(*args):
print(args)
f("小明", 18, "male") # 运行结果: ('小明', 18, 'male')
打印出来的是一个tuple,里面存放了(“小明”,18,”male”)这三个元素。
5.不定长参数 **kwargs
但是上面的args只能接收未命名的参数,那假如有类似于关键字参数的不定长参数该怎么办呢?python里面使用(**变量名)来接收不定长的命名变量参数。同样,python里面也约定俗成使用**kwargs接收不定长命名参数。kwargs接收了不定长参数之后,将这些参数放到一个字典里面,可以通过key获取到相应的参数值。
举个栗子:
def f(**kwargs):
print(kwargs)
f(name="小明", age=18, sex="male") # 运行结果: {'name': '小明', 'age': 18, 'sex': 'male'}
6. 参数混合使用
假如一个函数使用了上面所有种类的参数,那该怎么办?为了不产生歧义,python里面规定了假如有多种参数混合的情况下,遵循如下的顺序使用规则:
def f(必须参数,默认参数,*args,**kwargs):
pass
如果同时存在args和kwargs的话,args在左边
默认参数在必须参数的右边,在*args的左边
关键字参数的位置不固定(ps:关键字参数也不在函数定义的时候确定)
那么,假如有一个列表想要传递进入一个不定长的未命名参数的函数中去,可以在该列表前面加上*实现,同理如果想传递一个字典进入不定长命名参数的函数中去,可以在该字典前面加上**
举个栗子:
def f(*args, **kwargs):
print(args)
for i in kwargs:
print("%s:%s" % (i, kwargs[i]))
f(*[1, 2, 3], **{"a": 1, "b": 2})
运行结果:
(1, 2, 3)
a:1
b:2
7. 函数的返回值
要想获取函数的执行结果,就可以用return语句把结果返回
注意:
1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为 return 语句代表着函数的结束
2. 如果未在函数中指定return,那这个函数的返回值为None
3. return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。
import string
def upper_name(name):
name.upper() # 没有 return 时返回的是 None
def upper_name_re(name):
return name.upper() # 有 return 时可以返回 name.upper() 的结果
def upper_name_re_null(name):
return # 只有 return 时但是没有返回值实际返回的是 None
# 函数 upper_name()没有 return,所有返回值是 None
print(upper_name("b"))
# 函数 upper_name_re 有 return,所有返回的是 upper.name()的结果
print(upper_name_re("c"))
# 函数 upper_name_null 有 return,但是没有返回值所以返回的还是 None
print(upper_name_re_null("d"))
运行结果:
None
C
None