函数

返回值
返回值的3种情况
没有返回值 —— 返回None
不写return
只写return 执行到return之后就结束,表示结束一个函数
return None —— 不常用
返回1个值
可以返回任何数据类型
只要返回就可以接收到
如果在一个函数中有多个return的话就只执行第一个return
返回多个值
多个返回值用多个变量接收;有多少返回值就用多少变量接收
用一个变量接收多个返回值的时候,得到的是一个元组

参数
没有参数
定义函数和调用函数时括号里都不写内容
有一个参数
传什么是什么
有多个参数
位置参数
站在实参的角度上:
按照位置传参
按照关键字传参
混着用可以,但是 必须先按照位置传参,再按照关键字传参,不能给同一个变量传多个值

站在形参的角度上:
位置参数;必须传,且有几个参数就传几个值
只有调用函数的时候
按照位置传:直接写参数的值
按照关键字: 关键字 = 值
定义函数的时候
位置参数: 直接定义函数
默认参数,关键字参数: 参数名 = ‘默认的值’
默认参数的陷阱
如果默认参数的值是一个可变数据类型,那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源

动态参数: 可以接收任意多个参数
参数名之前加* , 习惯动态参数名为*args
参数之前加**,习惯动态参数名为**kwargs
顺序:必须先定义位置参数,*args,再定义默认参数,**kwargs

动态参数有两种:可以接收任意个参数
*args: 接收的是按照位置传参的值,组织成一个元组
**kwargs:接收的是按照关键字传参的值,组织成一个字典
args必须在kwargs之前(*args, **kwargs)

动态参数的另一种传参方式
def func(*args): # 站在形参的角度上,给变量加上*,就是组合所有传来的值
print(args)
func(1,2,3,4,5)
l = [1,2,3,4,5]
func(*1) # 站在实参的角度上,给一个序列加上*,就是将这个序列按照顺序打散


命令空间和作用域
命名空间
内置命令空间——Python解释器
就是Python解释器一启动就可以使用的名字存储在内置命名空间中
内置的名字在启动解释器的时候被加载进内存中

全局命名空间——我们写的代码,但不是函数中的代码
在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名

局部命名空间——函数
函数内部定义的名字
当调用函数的时候,才会产生这个名称空间,随着函数执行的结束,这个命名空间就结束了

在局部:可以使用全局、内置命名空间
在全局:可以使用内置命名空间,但是不能用局部命名空间
在内置:不能使用局部和全局的命名空间


在正常情况下,直接使用内置的名字
当我们在全局定义了和内置命名空间同名的名字时,会使用全局的名字
“当我自己有的时候,我就不找我的上级要了”
“如果自己没有,就找上一级要,上一级没有再找上一级,如果内置的命名空间都没有,就报错”
多个函数拥有多个独立的局部命名空间,不相互共享


作用域
全局作用域——作用在全局——内置和全局命名空间中的名字都属于群居作用域,使用globals()查看
局部作用域——作用在局部——函数(局部命名空间中的名字属于局部作用域,使用locals()查看)

globals 永远打印全局的名字
locals 根据locals所在的位置输出

对于不可变数据类型 在局部可以查看全局作用域中的变量
但是不能直接修改
如果想要修改,需要在程序的一开始添加global声明
如果在一个局部(函数)内声明了一个global变量,那么这个变量在局部所有的操作将对全局的变量有效


函数的嵌套定义
内部函数可以使用外部函数的变量
def outer():
def inner():
print('inner')
inner() # 如果不写这句就不会有任何现象
outer()
a = 1
def outer():
a = 2
def inner():
b = 2
a = 3
print(a)
print('inner')
def inner2():
nonlocal a # 声明了一个上面第一层局部变量
a += 1 # 不可变数据类型的修改
print('inner2')
inner2()
print('##a##: ', a)
inner()
print('**a**:', a)
outer()
print('全局:', a)

nonlocal 只能用于局部变量,找上层中离当前函数最近一层的局部变量
声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量


func --> 函数的内存地址
函数名() 函数的调用
函数的内存地址() 函数的调用
def func():
print('123')

func() # 函数名就是内存地址
func2 = func # 函数名可以赋值------
func2()

l = [func, func2] # 函数名可以作为容器类型的元素------
print(l)
for i in l:
i()

def func():
print('123')

def func3(f):
f()
return f # 函数名可以作为函数的返回值------

func3(func) # 函数名可以作为函数的参数-------
func4 = func3(func)
func4()


闭包:嵌套函数,内部函数调用外部函数的变量
def outer():
a = 1
def inner():
print(a)
print(inner.__closure__)
outer()

def outer():
a = 1
def inner():
print(a)
return inner
inn = outer()
inn()
闭包的好处就在于每次调用内部函数的时候就不用重复的生成外部的变量,节省了时间和内存空间


posted @ 2018-12-11 11:29  阿梵杰  阅读(224)  评论(0)    收藏  举报