函数一词来源于数学,编程中的"函数"与数学中的函数有很大的不一样。
(BASIC中叫subroutine,C中叫function,java中叫method)
java
定义:函数是指将一组语句的集合经过一个名字(函数名)封装起来,想执行这个函数,只需调用其函数名便可。 python
(1)减小重复代码:不然遇到重复的功能只能重复编写实现代码,代码冗余linux
(2)使程序变得可扩展:不然功能须要扩展时,须要找出全部实现该功能的地方修改之,没法统一管理且维护难度极大 c++
(3)使得程序变得易维护:不然代码的组织结构不清晰,可读性差编程
(1)内置函数:针对一些简单的功能,python解释器已经为咱们定义好了的函数即内置函数。对于内置函数,咱们能够拿来就用而无需事先定义,如len(),sum(),max()。数组
(2)自定义函数:很明显内置函数所能提供的功能是有限的,这就须要咱们本身根据需求,事先定制好咱们本身的函数来实现某种功能,之后,在遇到应用场景时,调用自定义的函数便可运维
参数的做用:可让函数更灵活,不仅能作死动做,还能够根据调用时传参的不一样来决定函数内部的执行流程。函数
# 无参函数 def sayhi(): # 函数名(小写便可) print("Hello,I'm nobody!") sayhi() # 调用函数,函数名指向上述代码指向的内存位置,加上括号才是执行代码 print(sayhi) # 函数sayhi指向的内存地址 # 单个参数的函数 def sayhi(name): print("hello",name) print("my name is black girl....", name) sayhi("tracy") # 多个参数函数 def calc(x,y): # 定义算数函数 res = x**y return res # 返回函数执行结果 a,b = 5,8 c = calc(a,b) # 结果赋值给变量c print(c) calc(2,10) # 直接写入参数
只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。所以,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量测试
能够是常量、变量、表达式、函数等,不管实参是何种类型的量,在进行函数调用时,它们必须有肯定的值,以便把这些值传送给形参。所以应预先用赋值,输入等办法使参数得到肯定值spa
def calc(x,y): # 形参 res = x**y return res a,b = 3,5 c = calc(a,b) # 实参 print(c) d = calc(2,3) # 实参
def stu_register(name,age,country,course): print("注册学生信息".center(50,'-')) print("姓名:",name) print("age:" ,age) print("国籍",country) print("课程",course) stu_register("山炮",22,"CN","python_devops") stu_register("丰收",23,"CN","linux") ''' 因为不少人国籍都是中国,能够将country设置为默认参数 默认参数: ''' def stu_register(name,age,course,country="CN"): # 非默认参数不能跟在默认参数后面 print("registration info".center(50,'-')) print(name,age,country,course) stu_register("jack",22,'c++') # 实参和形参按顺序一一对应 stu_register("rain",32,'dance','Korean') stu_register("Alfa",21,'python')
应用场景:正常状况下,给函数传参数要按顺序,不想按顺序能够用关键参数
定义:指定了参数名的参数就叫关键参数
关键参数必须放在位置参数(以位置顺序肯定对应关系的参数)以后
def stu_register(name,age,course,country='CN'): print("注册学生信息".center(50,'-')) print("姓名:",name) print("age:" ,age) print("国籍",country) print("课程",course) stu_register("绮珊",course='Python',age=22,country='JP') # 后三个均为为关键参数置于name位置参数以后 # stu_register("杉树",course='Python',22,country='JP') # 22为位置参数不能放在关键参数course以后 # stu_register("曼玉",22,age=25,country='JP') # age得到多个赋
形式参数中出现*,传递的参数就能够再也不是固定个数,会将传过来的全部参数打包为元组。
def send_alert(msg,*users): for u in users: print('报警发送给',u) # 方式一: # 报警,十个运维人员 send_alert('注意系统资源别浪了','Alex','jack','tracy','wood') # 方式二: # send_alert('注意内存紧张',['alex','jack','tracy','wood']) # 传入的参数是数据 send_alert('注意内存紧张',*['alex','jack','tracy','wood']) # 传入的参数是数组内的元素 # 传入的参数由(['alex','jack','tracy','wood']) ————>('alex','jack','tracy','wood')
若是动态参数后还有参数
# 方法一: def send_redalert(msg,*users,age): for u in users: print('CPU紧张',u) # send_redalert("alex","rain",22) # 22也会传递给*users send_redalert("alex","rain",age=22) # 方法二: def func(name,*args,**kwargs): print(name,args,kwargs) func('Alex',22,'tesla','500w',addr='湖北',num=123332313) # Alex (22, 'tesla', '500w') {'addr': '湖北', 'num': 123332313} d = {'degree':'primary school'} func('Peiqi',**d)
优势:使用*args和**kwargs能够很是方便的定义函数,同时能够增强扩展性,以便往后的代码维护。
返回值:函数外部的代码要想获取函数的执行结果,能够在函数里用return语句把结果返回。
注意:
一、函数在执行过程当中只要遇到return语句,就会中止执行并返回结果,能够理解return语句表明着函数的结束
二、若是未在函数中指定return,那这个函数的返回值为None
def stu_register(name,age,course='PY',country='CN'): print("注册学生信息".center(50,'-')) print("姓名:", name) print("age:", age) print("国籍", country) print("课程", course) if age > 22: return False else: return True registration_status = stu_register('阿斯顿',22,course="全栈开发",country='JP') if registration_status: print("注册成功".center(50,'-')) else: print("too old to be a student.") ''' 执行到return语句后,中止执行函数并返回结果 ''' def stu_register(name,age,course): print(name,age,course) # # if age > 22: # return 'sdfsf' # 返回值能够是任意值 # else: # return True # # return None # 到return语句后,中止执行函数并返回结果 # print('hahah') # return 1 return [name,age] status = stu_register('Peiqi',29,'安保') print(status)
局部变量:函数内定义的变量,只能在局部生效
全局变量:定义在函数外部一级代码的变量,整个程序可用(由上到下可用)
在函数内部能够引用全局变量。
变量查找顺序:若是全局和局部都有一个变量,函数查找变量的顺序是由内而外的。两个函数间互不可见
name = "Black girl" # 全局变量 def change_name(): # global name # (不建议使用global)在函数内修改全局变量,不能放在函数内局部变量后面 name = "黑色的姑娘" # 局部变量 print("在",name,"里面...",id(name)) change_name() print(name,id(name)) # 与函数内的变量内容彻底不一样 ''' 输出结果: 在 黑色的姑娘 里面... 4302993904 Black girl 4316351984 '''
函数内能够修改字典、列表、集合、对象、类、元组内的列表
names = ['Alex','Black Girl','Peiqi'] def change_name(): names = ['Alex'] del names[2] # names总体的内存地址不能修改只能引用,但其内部的元素是能够修改的 names[1] = "黑姑娘" print(names) change_name() print(names) ''' 输出结果: ['Alex', '黑姑娘'] ['Alex', '黑姑娘'] '''
做用域定义:一段程序代码中所用到的名字并不老是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的做用域。
age = 18 def func1(): age = 73 def func2(): age = 84 print(age) return 666 val = func1() print(val) ''' 输出:666 '''
# 函数名能够看成返回值 age = 18 def func1(): age = 73 def func2():... return func2 # 返回一个函数名# val = func1() print(val) ''' 输出:<function func1.<locals>.func2 at 0x101462598> ''' # 代码写完以后做用域已经生成,无论函数名传到哪里,只要执行都回回定义的地方往上找 age = 18 def func1(): age = 73 def func2(): print(age) return func2 # 返回一个函数名不带括号 val = func1() val() ''' 输出结果:73 '''
嵌套函数,就是指在某些状况下,您可能须要将某函数做为另外一函数的参数使用。
def func1(): print('alex') def func2(): print('eric') func1() ''' 输出:alex ''' def func1(): print('alex') def func2(): print('eric') func2() func1() ''' 输出: alex eric '''
总结:
函数内部能够再次定义函数
执行函数须要被调用
age = 19 def func1(): age = 73 print(age) # 寻找变量,先找本身的函数内,没有就找全局变量(一层一层往上找) def func2(): age = 84 print(age) # 寻找变量,优先本身函数、再找父级、爷爷级,最后找全局变量 func2() func1() # 输出:73 84
# 测试二: age1 = 19 def func1(): age1 = 73 def func2(): print(age1) # 按顺序往上找,找到父级的age=73 func2() func1() # 输出:73
age = 19 def func1(): def func2(): print(age) age = 73 func2() func1() """ 输出: 73 """ age = 19 def func1(): def func2(): print(age) func2() age = 73 func1() ''' 执行报错:free variable 'age' referenced before assignment in enclosing scope 73在func2后面,func2不知道该取哪一个参数 '''
为了不这种状况,声明变量尽可能写在前面。
age = 19 def func1(): global age # 此时已经拿到age=19,age=73尚未执行 def func2(): print(age) func2() age = 73 # 此时修改全局age=73 func1() print(age) """ 输出: 19 73 """ age = 19 def func1(): global age def func2(): print(age) age = 73 # 将全局变量age改成73,再执行func2,函数没有在func2\func1中找到age,继续到全局找age,但全局已经修改成73 func2() func1() print(age) """ 输出: 73 73 """
第一个程序,在global age时,函数已经拿到age=19,但此时age=73尚未执行,此时执行func2函数,打印age=19。随后修改全局变量age=73,直接打印age,所以输出73.
第二个程序,在global age时,函数拿到age=19,随后修改全局变量age=73,接着执行func2函数,打印age=73,打印此时的全局变量age,也一样输出73.