day10__基础(函数的进阶)

一、 函数的参数

1、形参角度:

  • 万能参数:

    动态参数分为两种:动态接受位置参数 *args,动态接收关键字参数:**kwargs.

动态接收位置参数:*args

def eat(*args):
print('我请你吃:',args)
eat('蒸羊羔儿','蒸熊掌','蒸鹿尾儿','烧花鸭','烧雏鸡','烧子鹅')
# 运行结果:
#我请你吃: ('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿', '烧花鸭', '烧雏鸡', '烧子鹅')

​ args就是一个普通的形参,但是如果你在args前面加一个,那么就拥有了特殊的意义,他将所有的位置参数聚合成一个元组赋值给了args

练习:传入函数中数量不定的int型数据,函数计算所有数的和并返回。

def  eat(*args):
    n = 0
    for i in args:
        n += i
    return n
print(eat(1,2,3,4,5,6))

动态接收位置参数: **kwargs

​ 函数定义时:**将所有的关键字参数聚合到一个字典中,将这个字典赋值给了kwargs

def func(**kwargs):
    print(kwargs)
func(name='alex',age=18,sex='boy')
结果:{'name': 'alex', 'age': 18, 'sex': 'boy'}
def func(*args,**kwargs):
    print(args) # ('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿')
    print(kwargs) # {'name': 'mrxiong', 'sex': '男'}
func('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿',name='mrxiong',sex='男')

2、形参角度的参数的顺序

位置参数必须在前面,即 :位置参数,默认参数。*args动态参数必须在位置参数后面

def fun(a,b,*args,sex='男'):
    print(a,b)
    print(sex)
    print(args)
 
fun(1,2,3,4,5,6,7,sex='女')

所以*args一定要在位置参数与默认值参数中间:位置参数,*args,默认参数

def fun(a,b,*args,sex='男',**kwargs):
    print(a,b)
    print(sex)
    print(args)
    print(kwargs)
fun(1,2,3,4,5,6,7,sex='女',name='Alex',age=12)

所以截止到此:所有形参的顺序为:位置参数,*args,默认参数,**kwargs。

3、形参角度第四个参数:仅限关键字参数

def fun(a,b,*args,sex='男',c,**kwargs):
    print(a,b)
    print(sex)
    print(args)
    print(c)
    print(kwargs)
fun(1,2,3,4,5,6,7,sex='女',name='Alex',age=12,c=6666)

上例中c是仅限关键字参数,它必须要放在*args和**kwargs之间

形参角度的所有形参的最终顺序为:位置参数,*args,默认参数,仅限关键字参数,**kwargs。

4、在函数的调用时,*代表打散

*args打散

def fun(*args):
    print(args)
fun(*[1,2,3],*[22,33,44])
输出结果:(1, 2, 3, 22, 33, 44)

**kwargs打散

def fun(*args,**kwargs):
    print(args)
    print(kwargs)
fun(**{'name':'mrxiong'},**{'age':18})

**在函数定义的时候代表聚合, 在函数执行的时候代表打散

二、名称空间,作用域

​ Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。
等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

​ 我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。

​ 代码在运行开始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;

​ 在函数的运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。

​ 现在我们知道了,py文件中,存放变量与值的关系的一个空间叫做全局名称空间,而当执行一个函数时,内存中会临时开辟一个空间,临时存放函数中的变量与值的关系,这个叫做临时名称空间,或者局部名称空间。

​ 其实python还有一个空间叫做内置名称空间:内置名称空间存放的就是一些内置函数等拿来即用的特殊的变量:input,print,list等等,所以,我们通过画图捋一下:

那么这就是python中经常提到的三个空间。

总结:

  • . 全局命名空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间
  • . 局部命名空间--> 在函数中声明的变量会放在局部命名空间
  • . 内置命名空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间

1、加载顺序

内置名称空间-------->全局命 名空间----------->局部命名空间

2、取值顺序

取值顺序(就近原则),单向不可逆

(从局部找)局部名称空间------->全局名称空间------>内置名称空间

img

3、作用域

全局作用域:包含内置名称空间、全局名称空间

局部作用域 :局部名称空间

局部作用域可以引用全局作用域的变量

报错示例:

count=1
def func():
    count+=2
    print(count)
func()
输出结果报错:
UnboundLocalError: local variable 'count' referenced before assignment

因为:局部作用域不能改变全局作用域的变量,当python解释器读取到局部作用域时,发现了你对一个变量进行修改操作,解释器会认为你在局己经定义过这个局部变量,它就从局部找这个局部变量,所以报错了

三、关键字:global、nonlocal

global

利用global在局部作用域也可以声明一个全局变量。

def func():
    global a
    a = 3
func()
print(a)

所以global关键字有两个作用:

1,声明一个全局变量。

2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。

nonlocal

​ nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal,当然这个用的不是很多,了解即可。

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)
add_b()

nonlocal关键字举例

nonlocal的总结:

1,不能更改全局变量。

2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。


另一作用:
glbals()、 locals()

globals() 返回的是字典,字典里面的键值对,全局作用域的所有内容

locals() 返回的是字典,字典里面的键值对,当前作用域的所有内容

posted @ 2020-06-26 15:20  MrXiong  阅读(35)  评论(0编辑  收藏