函数的使用原则
函数的使用必须遵循:先定义后使用的原则
函数的定义,与变量的定义是相似的,如果没有事先定义函数而直接引用就相当于在引用一个不存在变量名
定义阶段:只检测语法,不执行代码,当出现语法错误会抛出错误
def foo(): print('from foo') bar() def bar(): print('from bar')
调用阶段:执行代码的过程中,会检查逻辑问题,当引用一个不存在的变量名会抛错
foo()
函数参数
形参与实参
形参指的是函数定义时候标记的变量名,实参表示函数调用时候传入的实际数据参数,即标量值,形参在定义后是不可变的,而实参是可以变的。
def foo(x,y): #x,y即形参 print(x) print(y) foo(2,3) #2,3即实参
函数参数分类
位置参数:包括位置形参和位置实参,按照从左到右的数序依次定义的参数,用逗号分隔。
def foo(x,y): print(x) print(y) foo(2,3)
按位置定义的形参:在函数调用的时候,必须要有实参传入,实参的数量必须和形参的数量相同,不能多也不能少。
按位置定义的实参:要与与形参一一对应
关键字参数:实参在定义时,按照key=value形式定义,key值必须存在在形参里
def foo(x,y): print(x) print(y) foo(x=1,y=10) 或 foo(y=10,x=1) #关键字参数可以不用像位置实参一样与形参一一对应,指名道姓地传值
要注意的是,当位置实参和关键字实参同时传入的时候,位置实参必须在关键字实参之前
实参既可以用位置实参又可以用关键字参数,但是一个形参只能接受一个实参传入,不能接收多个
默认参数:在定义函数阶段,就已经为形参赋值,定义阶段有值,调用阶段可以不用传值
def func(x,y=10): print(x) print(y) func(1,20)
或 func(1)
默认形参必须在位置形参之后
函数调用时候,传入的实参可以不写默认形参的传入值,即只传入位置实参就可以了
当形参在大多数情况下是不变的时候,就可以定义成默认参数,默认参数通常定义成不可变类型,在定义的时候默认形参就已经被赋值了一次
可变长参数:可变长指的是实参的个数不固定
处理按位置定义的可变长度的实参:*
def func(x,y,*args): #x=1,y=2,args=(3,4,5,6) print(x,y) print(args) func(1,2,3,4,5,6)
*是用元组的方式接收多余出来的位置参数
调用函数时候使用func(1,2,*(3,4,5,6))也可传入参数,当遇到这种方式传入的时候,实际上和func(1,2,3,4,5,6)一毛一样,会自动拆分成位置参数。
处理按关键字定义的可变长度的实参:**
def func(x,y,**kwargs): #x=1,y=2,kwargs={'a':1,'b':3,'z':3} print(x,y) print(kwargs) func(1,y=2,z=3,a=1,b=3)
**是用字典的方式接收多余出来的位置参数
调用函数时候使用func(1,y=2,**{'a':1,'b':3,'z':3})传入参数时候,实际上和func(1,y=2,z=3,b=3,a=1)一毛一样,也会自动将字典拆分成关键字实参
def wrapper(*args,**kwargs): #可以接受任意形式,任意长度的参数 print(args) print(kwargs) wrapper(1,2,3,3,3,3,3,x=1,y=2,z=3)
位置实参被*接收,关键字实参被**接收
扩展:以下代码在后面装饰器能用到,wraper接收的传入参数会原封不动传给index
def index(name,group): print(name) print(group) def wrapper(*args,**kwargs): print(args) print(kwargs) index(*args,**kwargs) wrapper(1,23,3,13,4,315,3,15,23,4,x=1,y=2,c=3)
命名关键字参数:定义在*后的形参,必须得传入值,必须以关键字方式传入
def register(*args,name='egon',age): print(args) print(name) print(age) register(name='egon',age=18) register(1,2,2,3,age=10)
以上代码可以没有args,写成register(*,name='egon',age),将不能传入register(1,2,2,3,age=10)
形参定义顺序:位置形参,默认参数,*args,命名关键字参数,**kwargs
函数的返回值
返回值,return,一般有参函数需要有返回值
如果函数内没有return,那么会返回一个None
返回一个值,什么值都能返回
返回多个值需要用元组,不带括号也可以
return只能返回一次值,执行完return那么函数执行结束
def foo(): return 1 print('=====>') return 2 return 3 return 4 print(foo())
命名空间
名称空间:存放变量名与值的绑定关系
名称空间三种:
内置名称空间
python自带的名称,如print、len、max
解释器启动就会生成这个空间,是第一个生成的名称空间
全局名称空间
文件级别定义的名字
执行python文件的时候会生成,一般是顶头写的,流程控制语句内定义的变量名也放在全局名称空间
x=1 def func(): pass class Foo: pass import os if 1 > 2 : y=3
局部名称空间
定义在函数内部的,如嵌套定义
只有在函数调用生效,函数结束失效
def func(x,y): z=3 #x,y,z都是局部
三者加载顺序:内置名称空间、全局名称空间、局部名称空间
x=0 def f1(): x=1 def f2(): x=2 def f3(): x=3 print(x) f3() f2() f1()
作用域:作用范围
全局作用域
内置命名空间全局有用,全局名称空间对于全局都有用
局部作用域
局部命名空间局部有用,只在函数内部有效
找名字:从局部到全局,全局的局部是全局,函数的作用域范围在定义时候就固定死了
def func(): # print(globals()) #全局和内置名称 print(dir(globals()['__builtins__']) #全局和内置名称 print(locals()) #局部名称 print(globals() is locals())
函数嵌套
函数的嵌套调用:
def max2(x,y): if x> y : return x elif: return y def max4(a,b,c,d): res1=max2(a,b) res2=max2(res1,c) res3=max2(res2,d) return res3
函数的嵌套定义:
def f1(): def f2(): def f3(): print('from f2') print('from f2') f3() print('from f1') f2()
函数对象
函数是第一类对象: 指的是函数可以被当做数据传递
函数可以被引用
def func(): print('from func') f=func
可以当作函数的参数
def func(): print('from func') def foo(x): print(x) x() foo(func)
可以当做函数的参数
def foo(): print('from foo') def bar(): return foo f=bar() print(f) print(foo)
可以当作容器类型的元素
def select(): print('select function') func_dic={ 'select':select, } # print(func_dic['select']) func_dic['select']()