函数
函数的定义
1 def test(x): 2 "The function definition" 3 x += 1 4 return x
def:定义函数的关键字
test:函数名
():内可定义形参
“”:文档描述,非必要,但添加后可使得函数更易理解
x += 1:泛指代码块或程序处理逻辑,最好不要过多,让函数的功能简洁明了
return :定义返回值
调用运行:可以带参数也可以不带
函数名()
1 def test(x): 2 "The function definition" 3 x += 1 4 return x 5 y = test(5) 6 print(y) 7 # 6 8 def test1(): 9 "The function definition" 10 x = 5 11 y = x * 2 + 1 12 return y 13 y = test1() 14 print(y) 15 #11
注意:函数名一旦重名,后写的函数会覆盖先写的函数,因为Python是从上到下读取的。
使用函数的意义
实现特定的功能,避免重复代码
1、代码重用
2、保持一致性,易于维护
3、可扩展性
函数与过程
过程本质是函数,但是没有设定返回值,而在Python中,会自动为过程返回None
1 def test01(): 2 x = "I like Python" 3 print(x) 4 return x 5 t1 = test01() 6 print(t1) 7 """ 8 I like Python 9 I like Python 10 """ 11 def test02(): 12 x = "I like Python" 13 print(x) 14 t2 = test02() 15 """ 16 I like Python 17 None 18 """
返回值数:0 => None
返回值数:1 => 返回object
返回值数:>1 =>返回tuple
函数参数
形参:只有在被调用时才分配内存单元,在调用结束后,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
实参:可以是常量、变量、表达式、函数等,无论是何种类型,在进行函数调用时,它们都必须有明确的值,以便将这些值传给形参。因此,应预先用赋值、输入等方法使参数获得确定值。
位置参数和关键字:标准调用:实参和形参位置意义对应;关键字调用:位置无需固定
1 def test(x,y,z): #x,y,z是形参 2 h = x + y ** z 3 return h 4 t1 = test(1,2,3) #1,2,3是实参,属于位置参数 5 print(t1) 6 t2 = test(x = 2, y =2, z = 2) #属于关键字调用 7 print(t2) 8 """ 9 9 10 6 11 """
注意:二者混用时,位置参数一定要在关键字参数的 左边
默认参数
1 def test(x,type="None"): #type是默认参数 2 print(x) 3 print(type) 4 5 test(5) 6 test(5,type="Class") 7 """ 8 5 9 None 10 5 11 Class 12 """
参数组
**字典 *列表
1 def test(x,*args): 2 print(x) 3 print(args) 4 print(args[0]) 5 test(1,2,3,5) 6 """ 7 1 8 (2, 3, 5) 9 2 10 """
1 def test(x,*args,**kwargs): 2 print(x) 3 print(args) 4 print(kwargs) 5 test(1,2,3,5,7,9,y=9) 6 """ 7 1 8 (2, 3, 5, 7, 9) 9 {'y': 9} 10 """
全局变量与局部变量
定头写的是全局变量,在整个py文件中都可以调用
局部变量是子程序中定义的变量,只能在子程序中调用
1 name = "Sister" #全局变量 2 def test(): 3 name = "Jenny" #局部变量 4 print("change_name:",name) 5 test() 6 #change_name: Jenny
强制修改成全部变量的方法: 用global
1 name = "Sister" 2 def test(): 3 global name #将其定义为全局变量 4 name = "Jenny" 5 print("change_name:",name) 6 test() 7 print(name) 8 """ 9 change_name: Jenny 10 Jenny 11 """
注意:
1、如果函数内无global关键字,优先读取局部变量,能读取全局变量,无法对全局变量重新赋值,但对于可变类型,可以对内部元素进行操作
1 name = "Sister" 2 def test(): 3 name = "Jenny" 4 print("I love ", name) 5 test() 6 print(name) 7 """ 8 I love Jenny 9 Sister 10 """ 11 name1 = ["Allen", "Paul"] 12 def test1(): 13 name1.append("Jenny") 14 print("I love ", name1) 15 test1() 16 print(name1) 17 """ 18 I love ['Allen', 'Paul', 'Jenny'] 19 ['Allen', 'Paul', 'Jenny'] 20 """
2、如果函数中有global关键字,变量本质上就是全局的特定变量,可读取可赋值
3、全局变量名全用大写,局部变量名全用小写
函数的嵌套
1 def huangwei(): #执行顺序: 1→14→2、3→4→12→5、6→7→10→11→8、9→13 2 name = "黄伟" 3 print(name) 4 def liuyang(): 5 name = "刘洋" 6 print(name) 7 def nulige(): 8 name = '沪指花' 9 print(name) 10 print(name) 11 nulige() 12 liuyang() 13 print(name) #只调用这个子函数内部的变量 14 huangwei() 15 """ 16 黄伟 17 刘洋 18 刘洋 19 沪指花 20 黄伟 21 """
注意:可以用nonlocal直接指定上一级变量
前向引用 :函数即变量
1 def top(): 2 print("from top to bottom") 3 def bottom(): 4 print("from bottom to top") 5 top() 6 bottom() 7 """ 8 from bottom to top 9 from top to bottom 10 """ 11 def bottom(): 12 print("from bottom to top") 13 top() 14 def top(): 15 print("from top to bottom") 16 bottom() 17 """ 18 from bottom to top 19 from top to bottom 20 """
递归
def calc(n): print(n) calc(n) calc(10) #Wrong
1 import time 2 def calc(n): 3 print(n) 4 time.sleep(1) 5 calc(n) 6 calc(10) 7 #结果会不停输出10
递归的特性:
1、必须有一个明确的结束条件
满足某个条件 return
1 def calc(n): 2 print(n) 3 if int(n / 2) == 0: 4 return n 5 res = calc(int(n / 2)) 6 return res 7 res = calc(10) 8 print(res) 9 """ 10 10 11 5 12 2 13 1 14 1 15 """
2、递归的效率不高,递归层次过多会导致栈溢出。
作用域
1 def test01(): 2 print("test") 3 def test02(): 4 print("test2") 5 return 1 6 res = test02() 7 print(res) 8 # test2 9 # 1 10 def test1(): 11 print("test1") 12 def test2(): 13 print("test2") 14 return test1 15 res = test2() 16 print(res) 17 # test2 18 # <function test1 at 0x00000213CED9A510> 这是test 19 def test1(): 20 print("test1") 21 def test2(): 22 print("test2") 23 return test1 24 res = test2() 25 print(res()) 26 # test2 27 # test1 这是test1()的执行过程 28 # None 这是因为没有return值所以添加的默认值
函数运行的结果与其定义有关,与其在哪里调用无关
1 def name1(): 2 name = "1" 3 def name2(): 4 name = "2" 5 def name3(): 6 print(name) 7 return name3 8 return name2 9 z = name1() 10 print(z) 11 #<function name1.<locals>.name2 at 0x000001E8FFAFA488> 12 name2 = name1() 13 name3 = name2() 14 name3() 15 #2 16 name1()()() 17 # 2