所谓函数,就是把具备独立功能的代码块组织为一个小模块,在须要的时候调用闭包
函数的使用有两个步骤:
一、定义函数
二、调用函数app
函数的做用,代码重用,提升开发效率ide
def 函数名(): 函数封装的代码
def是英文define的缩写函数
函数名称应该可以表达函数封装代码的功能,方便后续的调用code
函数名称的命名应该符合标识符的命名规则对象
经过函数名()便可完成函数的调用递归
def func(name): # name是形式参数 print(name) # 函数体 func('kernel') # 执行函数,'kernel'是实参
定义了默认参数后,在函数调用时再也不须要传入,默认参数放在最后面作用域
def info(name,age,country='China') # name,age是普通参数,country是默认参数 print('name:',name) print('age:',age) print('国家:',country) info('kernel',21) # 调用时,没有传入country,就使用默认参数
正常状况下,给函数传递参数须要按照定义的顺序,不想按顺序就要使用关键参数,可是关键参数必须放在普通参数以后开发
def info(name,age,country='China') # name,age是普通参数,country是默认参数 print('name:',name) print('age:',age) print('国家:',country) info(age=21,name='kernel') # 使用关键参数,能够不按照顺序
*argsit
def demo(*args): print(args) # ('kernel', 21, '山东') demo("kernel",21,"山东")
**kargs
def demo(**kwargs): print(kwargs) # {'name': 'kernel', 'age': 21, 'address': '山东'} demo(name="kernel",age=21,address="山东")
特色:
函数内部调用本身
函数内部的代码是相同的,只是参数不一样,处理结果不一样
当参数知足一个条件时,函数再也不执行
栗子 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): 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("找的数在mid[%s]左面" % dataset[mid]) return binary_search(dataset[0:mid], find_num) else:# 找的数在mid右面 print("找的数在mid[%s]右面" % dataset[mid]) return binary_search(dataset[mid+1:],find_num) else: if dataset[0] == find_num: #find it print("找到数字啦",dataset[0]) else: print("没的分了,要找的数字[%s]不在列表里" % find_num) binary_search(data,66)
在函数中,针对参数使用赋值语句,会不会影响函数调用时的实参呢?
不会,只要针对参数使用赋值语句,不管是可变类型仍是不可变类型,都会在函数修改参数的引用,不会影响到外部变量的引用
def demo(num, num_list): print("start") # 赋值语句 num = 200 num_list = [4,5,6] print("id=%d,num=%d"%(id(num),num)) print("id=",id(num_list),"num_list=",num_list) print("end") gl_num = 100 # id=1875081376,gl_num=100 gl_list = [1,2,3] # id= 2164478175240 gl_list [1, 2, 3] print("id=%d,gl_num=%d"%(id(gl_num),gl_num)) # id=1875084576,num=200 print("id=",id(gl_list),"gl_list",gl_list) # id= 2164477982152 num_list= [4, 5, 6] demo(gl_num, gl_list) print("id=%d,gl_num=%d"%(id(gl_num),gl_num)) # id=1875081376,gl_num=100 print("id=",id(gl_list),"gl_list",gl_list) # id= 2164478175240 gl_list [1, 2, 3]
若是传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,一样会影响到外部的数据
def demo(name_list): name_list.append('end') print(name_list) name_list = ['kernel'] print("id=",id(name_list),"name_list",name_list) # id= 1980496082376 name_list ['kernel'] demo(name_list) print("id=",id(name_list),"name_list",name_list) # id= 1980496082376 name_list ['kernel', 'end'] demo(name_list) print("id=",id(name_list),"name_list",name_list) # id= 1980496082376 name_list ['kernel', 'end','end'] 咱们发现,外部变量的数据已经被改变了,可是它的引用一直没有改变 再看一个栗子 def demo(name_list=[]): name_list.append('end') print(name_list) demo() # ['end'] demo() # ['end', 'end'] demo() # ['end', 'end', 'end'] demo() # ['end', 'end', 'end', 'end'] 这不是咱们想要的结果,那怎么办呢? 咱们只须要将形参改为一个不可变类型就能够了 def demo(name_list=None): name_list = [] name_list.append('end') print(name_list) demo() # ['end'] demo() # ['end'] demo() # ['end'] demo() # ['end']
知足下列条件之一就能够称为高阶函数
map函数是Python内置的高阶函数,它接收一个函数和一个可迭代对象,并将函数做用在可迭代对象的每一个元素上,返回一个map对象
def func(x): return x * x r = map(func,range(10)) print(list(r)) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce函数也是Python内置的高阶函数,一样它接收一个函数和一个可迭代对象,可是函数必需要接收两个参数,reduce对可迭代对象的每一个对象调用函数,并返回最终结果
栗子1 from functools import reduce def func(x,y): return x * y r = reduce(func,range(1,10)) print(r) 调用过程func(func(func(func(func(func(func(func(1,2),3),4),5),6),7),8),9) 栗子2 from functools import reduce def func(x,y): return x * y r = reduce(func,range(1,10),10) print(r) 调用过程func(func(func(func(func(func(func(func(func(1,10),2),3),4),5),6),7),8),9)
filter函数也是Python内置的高阶函数,一样它接收一个函数和一个可迭代对象,函数的做用是对每一个元素进行判断,返回True和False,filter根据判断结果自动过滤掉不符合条件的元素
def func(x): if x % 2 == 0: return x r = filter(func,range(10)) print(list(r))
没有函数名
单条语句
语句的执行结果就是返回值
name_list = ['kernel','alex','qiyue','hobby','eric','aomikee'] r = sorted(name_list) print(r) r = sorted(name_list,key=lambda x:len(x)) print(r)
内部函数
def outer(): print('outer is running。。。') def inner(): print('inner is running。。。') inner() outer() outer is running。。。 inner is running。。。 内部函数inner存在于outer函数做用域内部,因此若是在outer外部区域调用inner函数就会报错
关于闭包
def outer(): x = 10 y = 10 def inner(): print(x+y) return inner fun = outer() fun() # 20 若是试图在一个内部函数里对外部函数的变量进行引用,这就是Python的闭包,因为闭包基于内部函数,因此闭包一样不能在外部进行调用
修改外部函数的变量
def outer(): x = 10 y = 10 def inner(): x = x + 1 print(x+y) return inner fun = outer() fun() # UnboundLocalError: local variable 'x' referenced before assignment
由于闭包是基于内部函数的,因此说将会启动Python解释器的屏蔽机制,这时候Python解释器就认为x是内部函数的局部变量,咱们此举正是试图对不存在的变量进行修改操做,因此报在定义以前引用错误,那么,怎么解决这个问题呢
Python2
若是外部函数做用域的变量是可变类型的,那么它就不会被Python解释器屏蔽掉 def outer(): x = [10] y = 10 def inner(): x[0] = x[0] + 1 print(x[0]+y) return inner fun = outer() fun() # 21
Python3
使用nonlocal关键字 def outer(): x = [10] y = 10 def inner(): nonlocal x x = x + 1 print(x+y) return inner
想一想下面的程序会运行成功吗?为何?
for i in range(10): pass print(i) # 9 代码执行成功,在Java/C#等强类型语言中,执行上面的语言会提示i没有定义,而在Python中确是能够执行的,那是由于Python中没有块级做用域,代码内的变量,外部能够调用
def say_hello(): name = 'kernel' print('hello ',name) print(name) # NameError: name 'name' is not defined 运行报错,name变量只在函数中起做用,因此全局是没法调用的
Python存在做用域链,首先从本身的做用域找,若是没有就去一级一级的往上找,若是没有找到就报错
name = "Alex" def f1(): name = "Eric" def f2(): name = "Kernel" print(name) f2() f1() # Kernel
name = "kernel" def f1(): print(name) def f2(): name = "eric" f1() f2() # Kernel 为何会输入Kernel而不是eric呢? 那是由于函数在未执行时,做用域链就已经造成了,因此f1会去全局变量中找name这个变量而不是f2
r = ([lambda :x for x in range(10)]) print(type(r)) for i in r: print(type(i)) print(i()) 返回的结果是一个列表类型,列表的每一个元素是一个函数,全部的函数运行出来都是9,为何呢? 那是由于函数在没有执行的时候,内部代码是不会执行的