---恢复内容开始---
1.函数的基本语法和特性
函数一词来源于数学,但编程中的【函数】概念与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫subroutine(子过程或者子程序),在Pascal中叫procedure(过程)和function,在java里面叫做method
定义:
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:
- 减少重复代码
- 使程序变的可扩展
- 是程序变的可维护
定义语法
>>> def sayhi(): #函数名 ... print("hello ,i'm nobody ") ... >>> sayhi <function sayhi at 0x7fc587a64840> >>> sayhi() #调用函数 hello ,i'm nobody >>>
可以带参数
#下面这段代码
>>> a,b = 5,8 >>> c = a ** b >>> print (c) 390625 >>>
改成用函数写
>>> def calc (x,y): ... res = x ** y ... return res ... >>> c = calc(a,b) >>> print(c) 390625 >>>
函数参数与局部变量
形参变量
只有在被调用时才分配内存单元,在调用结束时,即刻释放所有分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能在使用该形参变量
实参变量
可以是常量,变量,表达式,函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,因此应预先用赋值,输入等办法使参数获得确定值
>>> def calc (x,y):-----------形参 ... res = x ** y ... return res ... >>> c = calc(a,b)--------------实参 >>> print(c) 390625 >>>
默认参数
>>> def stu_register(name,age,nationality,course): ... print("-------注册学生信息--------") ... print("姓名:",name) ... print("age:",age) ... print("国籍:",nationality) ... print("课程:",course) ... >>> stu_register("Ryusei Ryo",23,'JP','actor') -------注册学生信息-------- 姓名: Ryusei Ryo age: 23 国籍: JP 课程: actor >>> >>> stu_register("王源",18,'CN','singer') -------注册学生信息-------- 姓名: 王源 age: 18 国籍: CN 课程: singer >>> stu_register("Jamie Dornan",35,'england','actor') -------注册学生信息-------- 姓名: Jamie Dornan age: 35 国籍: england 课程: actor >>>
def stu_register(name,age,nationality,country='CN'): 这样 这个参数在调用时不指定,那就是CN 指定的话就用指定的值
发现nationality这个参数 在调用时不指定,那默认参数就是CN
关键参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求,关键参数必须放在位置参数之后
>>> stu_register(age=22,name='morgana',nationality='CN',course='python') -------注册学生信息-------- 姓名: morgana age: 22 国籍: CN 课程: python
非固定参数
若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数
>>> def stu_register(name,age,*args): #*args就会把传入的参数变成一个元祖的形式 ... print(name,age,args) ... >>> stu_register("morgana",31) morgana 31 () >>> #后面这个()就是args,只是因为没传值,所以空 >>> stu_register("morgana",31,'CN','python') morgana 31 ('CN', 'python') >>>
还可以有一个**kwargs
>>> def stu_register(name,age,*args,**kwargs): #*kwargs会把多个传入的参数变成一个dict形式 ... print(name,age,args,kwargs) ... >>> stu_register("morgana",31) morgana 31 () {} #后面这个{} 就是kwargs ,只是因为没有传值,所以为空 >>> stu_register('morgana',31,'CN','python',sex='female',province='beijing') morgana 31 ('CN', 'python') {'sex': 'female', 'province': 'beijing'} >>>
局部变量
>>> name = 'morgana' >>> def change_name(name): ... print("before change:",name) ... name = 'katherine' ... print("after change",name) ... >>> change_name(name) before change: morgana after change katherine >>> print("在外面看看name改了么?",name) 在外面看看name改了么? morgana >>>
全局与局部变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量为全局变量
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序
当全局变量与局部变量同名时
在定义局部变量的子程序内,局部变量起作用:在其他地方全局变量起作用
返回值
要想获取函数的执行结果,就可以用return语句把结果返回
注意:
- 函数在执行过程中只要遇到return语句,就会停止执行并返回结果。so也也可理解为return语句代表着函数的结束
- 如果未在函数中指定return,那这个函数的返回值为None
嵌套函数
>>> name = "morgana" >>> def change_name(): ... name = "morgana2" ... ... def change_name2(): ... name = "morgana3" ... print("第3层打印",name) ... ... change_name2() #调用内层函数 ... print("第2层打印",name) ... >>> change_name() 第3层打印 morgana3 第2层打印 morgana2 >>> print("最外层打印",name) 最外层打印 morgana >>>
递归
>>> def calc(n): ... print(n) ... if int(n/2) == 0: ... return n ... return calc(int(n/2)) ... >>> calc (10) 10 5 2 1 1 >>>
递归特性
- 必须有一个明确的结束条件
- 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
递归函数实际应用案例,二分查找
>>> data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] >>> def binary_search(dataset,find_num): ... print(dataset) ... ... if len(dataset) >1: ... mid = int(len(dataset)/2) ... if dataset[mid] == find_num: #find it ... print("找到数字",dataset[mid]) ... elif dataset[mid] > find_num :# 找的数在mid左面 ... print("