python函数入门
知识内容:
1.函数的作用
2.函数的定义与调用
3.函数的返回值
4.函数的参数
5.局部变量与全局变量
6.作用域
一、函数的作用
1.复用代码
将可能重复执行的代码封装成函数,并在需要执行的地方调用函数,不仅可以实现代码的复用,还可以保持代码的一致性,便于日后的维护
2.提高可读性
使用函数可以提高代码的可读性,便于后期的代码维护,同时也有利于软件测试的进行
3.可拓展性
使用函数可以方便地进行功能的拓展,方便地进行功能添加,因为一个函数内部发生改变了,调用它的地方都可以发生改变。
二、函数的定义与调用
1. 函数的定义
(1)函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
(2)在python中定义函数的语法如下:
1 def 函数名(参数): 2 # 注释 3 函数体
在python中使用def关键字定义函数,然后是一个空格和函数名称,接下来是一对圆括号,在圆括号中是函数的参数,也就是形式参数列表,
多个参数用逗号隔开,圆括号之后是冒号,然后换行,最后是注释和函数体代码
(3)定义函数注意:
函数形参不需要声明变量,也不需要指定函数返回类型;即使函数不需要接受任何参数,也必须保留一对空的圆括号;括号后的冒号不能少;函数体相对于def关键字必须保证一个缩进(4个空格1个tab)
(4)函数名:
函数名:函数名是包含字母,数字,下划线的任意组合,但是不能以数字开头。虽然函数名可以随便取名,但是一般尽量定义成可以表示函数功能的,另外建议函数名不要以大写开头,一般类名以大写开头,函数名命名法则建议使用下划线连接法
函数名示例: show_result() input_numbers()
2.函数调用
1 返回值=函数名(参数1,参数2) 2 函数名(参数1,参数2)
示例:
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 定义一个函数输出费波纳西数列小于1000的项 4 5 6 # 定义函数: 7 def fib(n): 8 a, b = 1, 1 9 while a < n: 10 print(a, end=' ') 11 a, b = b, a+b 12 print() 13 14 15 # 调用函数 16 fib(1000) 17 18 函数定义于函数调用
3.函数的分类
函数的分类:内置函数与自定义函数
关于python的内置函数,看我的这篇博文:http://www.cnblogs.com/wyb666/p/8638891.html
三、函数的返回值
1.return的作用
return的作用: 结束一个函数的执行并返回,同时还可可以通过return返回一个任意类型的值
2.return返回的值
return返回的值可以是任何数据类型,字符串、列表、字典、数字、自定义类型等都可以,可以有一个或多个返回值,也可以没有返回值
函数中没有return语句或没有执行到return语句而返回或执行了不带任何值的return语句,则函数默认返回空值None;当函数返回多个值时,python将这些值放入元组中,返回这个元组。
示例:
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 函数有一个或多个返回值 4 5 6 def f(): 7 a = 1 8 b = 2 9 c = 3 10 print("函数有一个或多个返回值") 11 # return a # 一个返回值 12 return a, b, c # 多个返回值,以元组的方式返回 13 14 15 print(f())
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # return的作用 4 5 6 def f(): 7 print(123434) 8 # return 1 # 结束函数的执行 9 print(23234) 10 11 12 print(f())
总结:
返回值数=0,返回None
返回值数=1,返回object
返回指数>1,返回tuple
四、函数的参数
1.实参和形参
(1)形参: 形式参数,函数定义时圆括号内是使用逗号分开的形参列表,即函数定义的圆括号中的为形参,只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参
(2)实参: 实际参数,函数调用时圆括号内是使用逗号分开的实参列表,即函数调用的圆括号中的为实参,实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值
两者之间的区别: 形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存空间,实参是变量,占用内存空间,形参和实参之间的数据传递是单向的,实参可以传给形参,形参不能传给实参,在大部分情况下修改形参的值不改变对应的实参值
注:
(1)在大部分情况下修改形参的值不改变对应的实参值
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 形参与实参 4 5 6 def f(a): # a为形参 7 print("a is", a) 8 a += 1 9 print("a is", a) 10 11 12 n = 3 13 f(n) # n为实参 14 print("n is", n) 15 # 从结果可以看出在此程序中函数内部修改了形参的值,但是 16 # 对应的实参并没有发生改变
(2)但是在有些情况下可以通过特殊的方式在函数内部修改实参的值,如果传递给函数的是python可变序列,比如说列表、字符串,并且在函数内部使用下标或其他方法使可变序列增加、删除元素或修改元素值时,修改后的结果是可以反映到函数之外让实参发生修改
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 形参修改实参值(利用python可变序列) 4 5 6 def modify(v, item): 7 v[0] = v[0] + 1 # 修改列表元素值 8 v.append(item) # 为列表元素增加值 9 10 11 def modify2(d): 12 d['age'] = 18 13 14 15 # 修改列表: 16 a = [1, 3, 6, 9] 17 print(a) 18 modify(a, 666) 19 print(a) 20 21 # 修改字典: 22 d = {'name': 'wyb', 'age': 21} 23 print(d) 24 modify2(d) 25 print(d)
2.多个参数的传递
可以传递多个参数,多个参数之间用逗号隔开
在传参的角度上,调用函数时传参数有两种方式:
(1)按照位置传参数 -> 实参和形参位置一一对应
(2)按照关键字传参数 -> 位置无需固定
用法:1.位置参数必须在关键参数的前面
2.对于一个参数只能赋值一次
示例:
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 传递多个参数,实现比大小的功能 4 5 6 def cal_max(a, b): # 位置参数:按顺序定义参数 7 if a > b: 8 return a 9 else: 10 return b 11 12 13 # 1.按照位置传参: 14 print(cal_max(20, 30)) 15 print(cal_max(10, 20)) 16 # 2.按照关键字传参: 17 print(cal_max(b=50, a=30)) 18 # 3.位置和关键字传参混搭: 19 print(cal_max(10, b=30))
3.默认参数
python支持默认参数,即在定义函数时为形参设置默认值。在调用带有默认值参数的函数时,可以不用为设置了默认值的参数进行传值,此时函数将直接使用函数定义时设置的默认值进行传值。默认参数与下面的可变长参数均可以实现类似于函数重载的目的。
1 # 默认参数的使用: 2 def 函数名(...,形参名=默认值): 3 函数体
调用带有默认参数的函数时,可以不对默认参数进行赋值,也可以通过显式赋值来替换其默认值,具有极大的灵活性
1 # 默认参数实例: 2 3 4 def cal_sum(x, y=10): 5 return x + y 6 7 8 print("return of the sum(2, 3) is", cal_sum(2, 3)) 9 print("return of the sum(3) is", cal_sum(3))
注: 参数里既有默认参数也有普通参数时应该把普通参数放在默认参数左边,也就是说默认参数必须出现在函数形参列表的最右端且任何一个
默认参数右边都不能出现非默认参数(普通参数)
如下图所示:
4.关键参数
关键参数主要是指调用函数时的参数传递方式,而与函数定义无关。通过关键参数可以按参数名字传递值,实参顺序可以和形参顺序不一致,但不影响参数值的传递过程,避免了用户需要牢记参数位置和顺序的麻烦,使得函数调用和参数传递更方便。
注: 关键参数即为上面多个参数的传递中的按照关键字传递
1 # __author__ = "wyb" 2 # date: 2018/3/21 3 # 关键参数示例 4 5 6 def demo(a, b, c=5): 7 print(a, b, c) 8 9 10 demo(3, 4, 2) # 输出: 3 4 2 11 demo(c=1, b=2, a=6) # 输出: 6 2 1
5.可变长参数(*args和**kwargs)
可变长参数,也有人称之为动态参数,分别由*args和**kwargs接收参数,前者接收任意多个实参并将其放在一个元组中,后者接受类似于关键参数一样显式赋值形式的多个实参并将其放入字典中
1 # 元组可变长参数: 用*来标记 2 def show_message(message, *args): 3 for name in args: 4 print(message, name) 5 6 7 # 字典可变长参数: 用**标记 8 def check_book(**kwargs): 9 price = kwargs.get('Price', 0) 10 if price > 100: 11 print("**********The book is expensive!**********") 12 print("The book information are as follow: ") 13 for key in kwargs.keys(): 14 print(key, ": ", kwargs[key]) 15 print() 16 17 18 show_message("Good morning!", 'Jack', 'Tom', 'Alex') 19 check_book(author='James', Title='Economics', Price=87) 20 check_book(author='Jack', Title='Frans', Price=120, Date='2012-3-2') 21 check_book(Date='2003-8-9', author='Linda', Title='Chinese', Price=107) 22 check_book(author='Jin Lady', Title='English', Price=65) 23 check_book(author='Woz', Title='Python', Price=70) 24 check_book(author='clear', Title='Ruby', Date='2009-8-1')
上述代码中第一个函数中的参数为*args的用法,即无论调用该函数时传递了多少实参,都将其放入元组中,然后在函数中可以使用for循环遍历出其中的元素;
第二个函数值的参数则为**kwargs的用法,即在调用该函数时自动将接受的参数转换成字典,然后在函数中可以直接使用get获取字典中相应键对应的值。
五、局部变量与全局变量
1.定义
局部变量就是函数中定义的变量,其只在函数中生效,局部变量的作用域是在函数中,在函数之外无法调用局部变量;
全局变量是在程序一开头就定义的变量,全局变量的作用域是在整个程序中。当全局变量和局部变量同名时遵循内层屏蔽外层的原则,局部变量在函数中会屏蔽全局变量
1 # 局部变量与全局变量
2 # 全局变量:
3 name = "wyb"
4
5
6 def func():
7 # 局部变量:
8 name = "sss"
9 print("in the func")
10 print("change name: ", name)
11
12
13 print("name is: ", name)
14 func()
15 print("name is: ", name)
16
17 # 输出结果:
18 # name is: wyb
19 # in the func
20 # change name: sss
21 # name is: wyb
注: 局部变量为列表、字典、集合时局部变量就可以在函数里改全局变量!如果是字符串、数字类型就不能!
2.局部变量与全局变量
一般来说函数中的局部变量是无法修改全局变量:这里的修改指的是赋值,但是对于可变数据类型,可以对全局变量中的某个元素进行赋值;
如果函数中无global关键字,优先读取局部变量,只能读取全局变量,无法对全局变量进行赋值(类似name="newname"),但是对于可变数据类型(列表、字典)可以对其中的元素进行赋值操作,详细代码看下面的实例:
1 name = "wyb" 2 3 4 def func1(): 5 name = "666" 6 print(name) # 输出666 7 8 9 def func2(): 10 print(name) # 输出wyb 11 12 13 def func3(): 14 name = "666" # 创建一个局部变量未改变全局变量 15 print(name) # 输出666 16 17 18 func1() 19 func2() 20 func3() 21 print(name) # 输出wyb
1 name = ["wyb", "sss", "kkk"] 2 3 4 def func1(): 5 name = "666" # 创建局部变量未改变全局变量 6 print(name) # 输出666 7 8 9 def func2(): 10 name.append("root") # 向全局变量中添加元素(可变数据类型(列表、字典)才可以!) 11 print(name) # 输出['wyb', 'sss', 'kkk', 'root'] 12 13 14 func1() 15 print(name) # 输出['wyb', 'sss', 'kkk'] 16 func2() 17 print(name) # 输出['wyb', 'sss', 'kkk', 'root']
函数中可以使用global关键字来声明局部变量为全局变量,然后对其可以直接进行赋值操作,此时改变局部的值就相当于改变了全局的值,详细代码看下面一段实例:
1 #在函数中修改全局变量
2 #全局变量:
3 name = "wyb"
4
5
6 def func():
7 # 局部变量:
8 global name # 定义global变量修改全局变量
9 name = "sss"
10 print("in the func")
11 print("change name: ", name)
12
13
14 print("name is: ", name)
15 func()
16 print("name is: ", name)
17
18 # 输出结果:
19 # name is: wyb
20 # in the func
21 # change name: sss
22 # name is: sss
注: 请注意在程序中千万不要用global改全局变量,这样做会影响程序的可读性和调试难度!
六、作用域
python作用域 -> 函数(与JavaScript类似)
C、Java的作用域 -> {}
1.命名空间 -> 存放变量名字与其对应的值的关系
- 全局命名空间(globals):创建的存储全局变量的“变量名与值的关系”的空间叫做全局命名空间
- 局部命名空间(locals):在函数的运行中开辟的临时的空间叫做局部命名空间,是函数内的名称空间,包括函数参数和局部变量
- 内置命名空间(builtins):内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法
注:
- 加载顺序:内置(程序运行前加载)-->全局(从上到下顺序加载进来的)-->局部(调用的时候加载)--->内置
- 取值:在局部调用:局部命名空间--->全局命名空间--->内置命名空间; 站在全局范围找:全局---->内置---->局部
- 使用注意:全局中不能使用局部的;局部中可以使用全局的
1 n = 10 2 3 4 def func(): 5 n = 20 6 print("in the func: ", n) 7 8 def func2(): 9 n = 30 10 print("in the func2: ", n) 11 12 def func3(): 13 print("in the func3: ", n) 14 15 func3() 16 17 func2() 18 19 20 func() 21 # 输出结果: 22 # in the func: 20 23 # in the func2: 30 24 # in the func3: 30
2.作用域:就是作用范围,命名空间和作用域是分不开的
python中的作用域:
- 全局作用域:全局命名空间与内置命名空间的名字都属于全局范围在整个文件的任意位置都能被引用,全局有效
- 局部作用域:局部命名空间,只能在局部范围内生效
- 当定义完成后,作用域就已经生成,作用域链向上查找
python的变量作用域简单说就是全局变量在局部(比如函数里)依然有效,但是函数里的局部变量只在该函数里有效,在其他地方就无效
3.查看作用域
globals函数:查看全局作用域的名字 -> print(globals())
locals函数:查看局部作用域的名字 -> print(locals())