昨日补充:
命名关键字参数
命名关键字参数就是一个稍微有点特殊的参数而已。
定义:在函数定义的过程中,在*与**之间定义的参数就叫做命名关键字参数。
特点:命名关键字参数必须按照key=value的形式对函数进行传值。
例:
def func(a, b, *args, c, **kwargs):
pass
# 这里的c参数就是命名关键字参数。必须按照key=value的形式传值。
# 命名关键字参数还可以这样写
def func(a, b, *args, c):
pass
# 这里的c也是明明关键字参数。说白了明明关键字参数就是跟在*后面的参数
# 但是如果参数里还有**,命名关键字参数必须放在*后面,**前面
今日内容:
1. 函数对象
函数是第一类对象:函数的内存地址可以像变量值一样去使用
最简单的来说吧:学变量的时候我们说过,定义变量时,申请一块内存空间存放值,然后将这个内存空间的地址与变量名建立联系,我们通过变量名就可以访问到值并做一些操作。函数也是一样的,我们定义函数时,申请了一块空间存放函数的代码块,然后将这个内存空间的地址与函数名建立联系。我们同样可以通过函数名去做一些和变量一样的操作。
首先我们要声明:函数名()这样会触发函数的代码块的执行,就不是我们上面所说的通过内存地址去做操作了。
函数名就像变量一样,所以我们可以变相的说这样一句话(函数即变量。)这句话不是python给我们规定的,而是我们为了更好的理解函数名的操作而自己创造的!!!
(1)变量值可以被引用
a = 1
b = a
# 这样我们就将变量a的值引用给了b
# 函数名同样可以这样操作
def func():
pass
foo = func
foo()
# foo()就相当于是调用func函数
# 这样我们就把func函数的内存地址与foo建立了联系。通过foo我们一样可以得到与func一样的执行效果
(2)变量值可以当做参数传给另一个函数
def foo(name):
print(name)
a = 'Catalog Spri'
foo(a)
# 我们将变量a当做参数传入foo函数,那么函数也可以当做参数传入函数
def func():
print('我是函数func')
foo(func)
# 这样我们就实现了将func函数当做参数传入foo函数
(3)变量值可以当做函数的返回值
def func(name):
return name
a = 'Catalog Spri'
func(a)
# 执行func函数,变量a的值就会当做返回值被func函数返回。
# 上面我们说了函数名可以当做变量传入函数
# 当函数名作为参数在这里传入func函数,函数名就会当做返回值被返回
func(foo)
(4)变量值可以当做容器类型的元素
# 什么叫容器类型:像列表,元组,字典等
# 变量值可以放入容器类型当做元素,函数名也可以
name = ['a', 'b']
def foo():
pass
def func():
pass
name = [foo, func]
# 放入容器类型可以让我们对函数的调用有更多的方法
# 应用:
def register():
print('注册....')
def login():
print('登录....')
def pay():
print('支付....')
def transfer():
print('转账....')
func_dic={
'1':register,
'2':login,
'3':pay,
'4':transfer
}
# func_dic['1']()
while True:
print("""
0 退出
1 注册
2 登录
3 支付
4 转账
""")
choice=input('请输入你的操作: ').strip()
if choice == '0':break
if choice not in func_dic:
print('输错的指令不存在')
continue
func_dic[choice]()
# 实现了两行代码调用多个函数,令代码美观了很多
2. 函数嵌套
函数的嵌套分为两种:
1. 定义过程中的嵌套:在函数定义的代码块中又定义了一个函数
def func():
print('我是func')
def foo():
print('我是foo')
# 在定义func函数的时候,我们又定义了foo函数。这就是定义过程中函数的嵌套
2. 调用过程中的嵌套:在函数定义的代码块中调用了另一个函数
def foo()
print('我是foo')
def func():
foo()
print('我是func')
# 在定义func函数的过程中,我们调用了foo函数。这就是调用过程中函数的嵌套
3.名称空间与作用域(重点知识)
一、名称空间(NameSpace)
1. 名称空间简介
前面讲变量的时候我们说过定义变量的过程都干了哪些事:申请内存空间存放值,将内存空间的地址与变量名建立联系。那么现在我们来思考一个问题,变量名被存到哪里去了?
首先我们可以肯定变量名是被存放到内存里面了。当我们打开python解释器的时候,Python解释器就帮我们申请了一块内存空间,专门用来存放变量名、函数名等这些东西。这块内存空间就叫做名称空间
说的稍微官方一点就是:名称空间就是用来存放名字与值内存地址绑定关系的地方
2. 名称空间分类
名称空间分为三大类:
内置名称空间
内置名称空间是用来存放python内置关键字的地方,在Python解释器运行的那一刻就已经定义好了,在python解释器关闭的时候就会自动清除
例如:print这种内置关键字就存放在内置名称空间中
全局名称空间
在python代码的顶级定义的名字就叫做全局名字(如果这个理解不了,可以换种方式理解,除了内置名称和局部名称,其他全是全局名称),存放在全局名称空间,全局名称空间在python程序执行的时候定义,在python程序结束的时候自动清除
a = 1
b = 2
name = 'Catalog Spri'
这些就叫做全局名称,存放在全局名称空间
局部名称空间
在函数体内定义的名称就叫做局部名称,存放在局部名称空间,函数的局部名称空间在调用函数时定义,在函数执行结束时自动清除
def func():
name = 'Catalog Spri'
这里面的name就是在函数体内定义的,叫做局部名称,存放在局部名称空间。
# 三种名称空间的产生的先后顺序: 内置->全局->局部
# 查找名字的顺序:从当前位置往外一层一层查找
# 如果当前在局部名称空间: 局部->全局->内置
# 如果当前在全局名称空间: 全局->内置
二、作用域
作用域就是指名称的作用范围
重点:作用域关系是在函数定义阶段就已经固定死了,与函数调用的位置没有关系!!!(重点重点重点)
对于全局名称来说:在全局定义的名称,在全局都可以使用
全局作用域可以访问到全局名称与内置名称但是不能访问到局部名称
def func():
name = 'Catalog Spri'
print(name)
# 这样就是试图在全局访问局部变量,会报错,说name这个变量没有被定义
对于局部名称来说:在局部定义的名称,只能在当前局部使用
局部作用域可以访问到该局部内的名称和全局名称以及内置名称
def func():
name = 'Catalog Spri'
# 这是一个局部,可以称之为局部1
def foo():
age = 19
# 这是另一个局部,可以称之为局部2
print(name)
# 局部与局部是相互独立的,在局部2中访问局部1中的变量名是访问不到的
# 作用域重点示例:
def func():
name = 'Catalog Spri'
print(name)
name = 'Alex'
func()
# 执行func函数,依旧会打印Catalog Spri,而不会打印alex,这就是我们前面所说的重点:
# 作用域关系是在函数定义阶段就已经固定死了,与函数调用的位置没有关系
4. 闭包函数
闭:封闭,将函数封闭在一个局部中,也就是将函数缩进到另一个函数的代码块中,就叫封闭
包:就是在该封闭函数外面包裹一层作用域,使它只接受从该作用域传过来的名称。
闭包函数就是将函数所学的知识点串用到一起,不是什么难点。
首先我们来定义一个函数:
name = 'Alex'
def inner():
print('我是inner', name)
定义好这个函数以后,我们想要实现对该函数的封闭:
name = 'Alex'
def outter():
def inner():
print('我是inner', name)
将inner函数缩进到outter函数内部,就实现了inner函数的封闭
再来我们将函数包裹一层作用域:
def outter():
name = 'Alex'
def inner():
print('我是inner', name)
前面我们说过,函数定义阶段就已经把作用域限制死了,调用阶段再定义一个name,inner函数也会按照定义时的作用域去查找变量。
这样我们就实现了对inner函数的闭包。
但是我们无法在全局访问到inner函数,而我们又想要使用inner函数,这要怎么办呢?
此时,return就派上了用场:
def outter():
name = 'Alex'
def inner():
print('我是inner', name)
return inner
f = outter()
我们将inner函数名作为outter函数的返回值,在调用outter函数时,会产生一个返回值:inner函数的内存地址。我们将返回值赋值给变量名f。
f() 就可以实现对inner函数的调用。
这就是闭包函数的用法。
闭包函数给了我们一个新的传参方法。我们可以通过将函数闭包来给函数传参。
闭包函数的具体应用就是装饰器。这个知识点我们明天会讲到。有兴趣的小伙伴可以关注一下,江湖有缘,我们明天见。