六、Python中的函数

6 Python中的函数

6.1 初识python函数

a.初步接触函数:
了解查看一个函数可用: help(函数名);
查看函数之禅: import this ;
函数三大特点:功能性(实现某些功能)、隐藏细节(方便调用)、避免编写重复代码;
示例如图:

b.函数定义及运行特点
特点:
a.自上而下的执行过程,函数需要先定义才能通过调用使用;
b.定义函数或变量名时,要尽量避免和python的内置函数同名,
系统默认递归次数为995次,超出在报错,可用import sys、setrecursionlimit(1000000)来设置递归次数,目前实际上达不到百万次的递归;
c.函数遇到return就会终止,不会再往下执行!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def funcname(parameter_list):
pass
# def 用来声明是一个函数
# 参数列表可以没有
# 可在结尾用 return 返回值, 或者不返回:None

"""
def print(st): # 函数名与内置print同名
print(st) # 函数内部又调用,递归到死
# 没有返回值,就相当于 return none
"""

def cys(cat,dog):
print('I\'m a cat,my name is ' + cat)
print('hi,i\'m ' + dog + ',and i\'m a dog')
return (cat + '|' + dog)

house_animals = cys('kitty','samo')
print(house_animals)

# result:
g:\Python\Demon2\pk1>fc.py
I'm a cat,my name is kitty
hi,i'm samo,and i'm a dog
kitty|samo

6.2 函数返回多个结果及接收

注意:
a.建议用有意义、有名称的变量来接收函数的返回结果(易于后期维护,涉及到‘序列解包’);
b.不建议用元组(tuple)的索引来进行解包操作取值(不够清楚,含糊不清);

1
2
3
4
5
6
7
8
9
10
11
12
13
def cal(fruit,meat):
fruit_cal = fruit * 2
meat_cal = meat * 3
return fruit_cal,meat_cal
# 输入食品名称(模糊查询,或者根据输入的字提示那些可查询),
# 通过查询 食品名--卡里路表,返回卡里路的值
cals = cal('apple','mutton')
print(cals[0],cals[1]) # 不推荐使用这种方式接收函数返回值
print(type(cals)) # 为tuple(元组)类型

#推荐此种方式(易于后期维护)
orange_cal,egg_cal = cal('orange','egg')
print(orange_cal,egg_cal)

6.3 序列解包与链式赋值

1
2
3
4
5
6
7
8
9
a,b,c = 1,2,3 # 多元赋值
print(a,b,c)

d = 4,5,6
q,w,e = d # 序列解包:变量数要的等于序列中元素的个数
print(q,w,e)

z=x=c = 99 # 链式赋值
print(z,x,c)

6.4 参数

参数(关键在于函数调用而不是定义上):
①必须参数:函数的参数列表中定义的必须赋值的参数。必须放在参数列表的前面。
②关键字参数:可以在函数调用时明确指出实参是传给哪个形参的,不一定要按照形参顺序。如:
def add(x, y):

return result
c = add(y = 3, x = 2)
③默认参数:没有设置默认值的参数必须传递实参。
④可变参数。如:
def demo(*param):
print(param)
print(type(param))
demo(1,2,3,4,5)
结果为:
1,2,3,4,5
tuple类型
也就是说python会自动将可变参数对应的实参转化成tuple类型。

6.4.1 必须参数和关键字参数
1
2
3
4
5
6
7
8
def add(x,y):   # 形参(必须参数,调用时必须一一赋值)
res = x+y
return res

sum = add(1,2) # 实参
print(sum)

rt = add(y=3,x=8) # 关键字参数 顺序随意,提高可读性
6.4.2 默认参数

注意:
①所有非默认参数必须在所有默认参数前,不论定义函数还是调用时都是一样。
②要想向某一特定默认参数传递参数应该使用关键字参数指定要改变的默认参数,否则将根据默认参数顺序依次匹配。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#默认参数必须放在非默认参数后面
def pri_stu_info(name,gender='male',age = 18,province='ShenZhen'):
print('姓名: ' + name)
print('性别: ' + gender)
print('年龄: ' + str(age))
print('籍贯: ' + province)
pri_stu_info('Tina','female',15,'Henan')
pri_stu_info('Tom','male',16) # 按照顺序就不需要通过关键字来赋值
pri_stu_info('LiLi','fmale')
# 必须通过关键字来赋值,否则会按照顺序,重新赋值
pri_stu_info('XiaoBai','fmale','ShanDong')
pri_stu_info('Jade',gender='female',province='BeiJing')
#会报错,非默认参数必须在默认参数前,27没有遵循
pri_stu_info('Albee',gender='female',27,province='BeiJing')

6.4.3 可变参数

a. 定义一个拥有可变参数的函数: 括号内形参前加星号,
python会把可变参数列表(实参)组装成一个元组tuple;
b. 调用可变参数函数时,实参里直接把所有参数一一列出,用逗号隔开即可;
c. 如果要传递的参数本省是一个tuple,为了避免结果出现二维tuple(即两个括号)的情况,在调用函数时实参括号里也加上星号
。*的作用相当于解包,即把元组里的每个元素平铺传入可变参数函数中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def vf(*param):
print(param)
print(type(param))
#必须参数、可变参数、默认参数(完全没必要搞的这么复杂)
def vf2(param1,*param,param2 = 2):
print(param1,param2,param)
print(type(param))

vf(1,2,3) # 会自动转换为一个元组
print('==1===')
vf((1,2,3)) # 传入的是元组,自动转换为2维元组
print('==2===')
a = (1,2,3)
vf(*a) # * 将元组 a 平铺开来,再传给函数
print('==3===')
vf2('yes',1,2,3,param2='22')
#result:
g:\Python\Demon2\pk1>f6.py
(1, 2, 3)
<class 'tuple'>
==1===
((1, 2, 3),)
<class 'tuple'>
==2===
(1, 2, 3)
<class 'tuple'>
==3===
yes 22 (1, 2, 3)
<class 'tuple'>

PS: 没必要死记各种参数之间的顺序,函数参数列表设计的要简约一些。

6.4.4 关键字可变参数

关键字可变参数:
格式:
def demo(param):
pass
这样在调用时可以传递多个关键字参数,此时python会将其转化为字典类型dict。若还想传递字典类型而不转化为多维数组,调用时需加上

小技巧:
遍历字典类型数据方法:
for key,value in param.items():
print(key, ‘:’, value)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 关键字可变参数
def city_tem(**param):
print('传入的参数变为:'+str(param))
print(type(param))
for city,tem in param.items():
print(city + ' : ' + tem)

city_tem(nj='32c',bj='29c',gs='25c')
print('=======')

ct = {'NanJing':'32C','BeiJing':'29C','GanSu':'25C'}
city_tem(**ct)

#Result:
g:\Python\Demon2\pk1>f7.py
传入的参数变为:{'nj': '32c', 'bj': '29c', 'gs': '25c'}
<class 'dict'>
nj : 32c
bj : 29c
gs : 25c
=======
传入的参数变为:{'NanJing': '32C', 'BeiJing': '29C', 'GanSu': '25C'}
<class 'dict'>
NanJing : 32C
BeiJing : 29C
GanSu : 25C
6.4.5 变量作用域

a. 局部变量和全局变量
python中可以在for循环外部访问for循环内部定义的变量,if-else和while也是如此;
因为在python里for、while和if-else不能形成作用域,所以其中的变量视作与函数内变量同一级别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def demon():
c = 3 # 局部变量(在函数中优先级比全局变量高)
print(c)
c = 12 # 全局变量
demon()

def cat():
b = 1
for i in range(0,9):
s = 's' #for内部
b += 1 #这里可以引用b,还在函数cat()内部
print(s) #可以在for循环外边访问for循环内部的变量
print(b)
cat()

m = 0
def func1():
#m = 1 #作用域链(逐级寻找)
def func2():
#m = 2
print('m = '+str(m))
func2()

func1()

b.global关键字
在整个应用程序里都可以使用, 而不仅仅是在模块中使用;
示例如图:

分享到