python-函数进阶-动态传参,名称空间,作用域的问题

python

一.函数的动态的动态参数

动态参数分为两种:动态接收位置参数、动态接收关键字参数。

1.*args  位置参数动态传参

#  顺序: 位置参数=>*args(arguments) => 默认值参数
# * 在这里表示接收位置参数的动态传参, 接收到的是元组
def chi(name,*food, location="天津"): # 参数名是food *表示动态传参
print(location)
print(name+"要吃", food)

chi("juan","驴打滚","二姑包子","桂顺斋","长春")

#长春
#juan要吃("驴打滚","二姑包子","桂顺斋")

动态接收参数的时候要注意:动态参数必须在位置参数后面。具体请看下面几个示例:

 def chi(*food, a, b):

print("我要吃", food, a, b)

chi("大米饭", "小米饭", "黄瓜", "茄子")

# 这时程序会报错,因为前面传递的所有位置参数都被*food接收了,a和b永远接收不到参数

# TypeError: chi() missing 2 required keyword-only arguments: 'a' and 'b'

# 所以上例可以改成以下代码

def chi(*food,a,b):

print("我要吃",food,a,b)

chi("大米饭","小米饭",a="黄瓜",b="茄子") # 必须用关键字参数来指定

# 这时候a和b就有值了,但是这样写的话位置参数就不能用了,

# 所以,我们要先写位置参数,然后再用动态参数

def chi(a,b,*food):

print("我要吃",a,b,food)

chi("大米饭","小米饭","馒头","面条")

# 结果为:我要吃 大米饭 小米饭 ('馒头', '面条')

# 前面两个参数用位置参数来接收,后面的参数用动态参数接收

def chi(a,b,c="馒头",*food):

print(a,b,c,food)

chi("香蕉","菠萝") # 香蕉 菠萝 馒头 ()默认值生效

chi("香蕉","菠萝","葫芦娃") # 香蕉 菠萝 葫芦娃() 默认值不生效

chi("香蕉","菠萝","葫芦娃","口罩") # 香蕉 菠萝 葫芦娃("口罩",)默认值不生效

# 我们发现默认值参数写在动态参数前面,默认值只有一种情况可能会生效。

# 即默认值生效时,其后的动态参数接收的参数一定是0个

def chi(a,b,*food,c="娃哈哈"):

print(a,b,food,c)

chi("香蕉","菠萝") #香蕉 菠萝 ()娃哈哈 你默认值生效

chi("香蕉","菠萝","葫芦娃") #香蕉 菠萝 ("葫芦娃",) 娃哈哈 默认值生效

chi("香蕉","菠萝","葫芦娃","口罩") #香蕉 菠萝 ("葫芦娃","口罩")娃哈哈 默认值生效

# 将默认值参数放在动态参数之后,我们发现所有的默认值都生效了,

# 这时候如果不给出关键字传参,那么你的默认值是永远都生效的。

综上可得参数顺序:位置参数,*args(动态接收位置参数),默认值参数

2,动态接收关键字参数   **kwargs
python中可以动态传参,但是*args这种情况只能接收位置参数,无法接收关键字参数

使用关键字参数的动态传参:就是用**kwargs来接收动态关键字参数,具体示例如下:

    def func(**kwargs):

print(kwargs)

func(a=1,b=2,c=3) # 结果为:{'a': 1, 'b': 2, 'c': 3}

func(a=1,b=2) # 结果为:{'a': 1, 'b': 2}

# 这时候接收的是一个dict字典

最终可得形参顺序:位置参数  >  *args  >  默认值参数  >  **kwargs,这四种参数可以任意进行使用。

   # 如果想要接收所有的参数可以这样写

# 当你不知道需要需要传递多少参数的时候可这样写,

# 因为这样可以传递任意参数,即无敌

def func(*args,**kwargs):

print(args,kwargs)

func("麻花藤","马云",wtf="胡辣汤")

3,动态参数的聚合与实参的打散

  综上可知,在形参位置上*表示把接收到的位置参数聚合(组合)成一个元组,**表示把接收到的关键字参数聚合(组合)成一个字典,那么在实参位置上给一个字符串,列表,元组或者集合(可迭代对象即可),并在其前面加个*表示把这个序列打散,如果是一个字典,则在其前面加上**。具体示例如下:

def fun(*args):

print(args)

lst = [1,4,7]

# fun(lst[0],lst[1],lst[2])

fun(*lst) # 可以使用*把一个列表按顺序打散

s = "臣妾做不到"

fun(*s) # 字符串也可以打散(可迭代对象即可)

def fun(**kwargs):

print(kwargs)

dic = {"a":1,"b":2}

fun(**dic)

4,函数的注释(文档注释)

 def chi(food,drink):

"""

这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃

:param food: 参数food是什么意思

:param drink: 参数drink是什么意思

:return: 返回的是什么东东

"""

print(food,drink)

return "very good"

二、命名空间

   def fun():

a =10

print(a)

fun()

print(a) # a不存在了已经

命名空间的分类:

  1,全局命名空间-->我们直接在py文件中,函数外声明的变量都属于全局命名空间;

  2,局部命名空间-->在函数中声明的变量会放在局部命名空间;

  3,内置命名空间 -->存放python解释器为我们提供的名字,如int,str,list这些都是内置命名空间;

加载顺序:

  1,内置命名空间

  2,全局命名空间

  3,局部命名空间(函数被执行的时候)

取值顺序:

  1,局部命名空间

  2,全局命名空间

  3,内置命名空间

 a = 10

def dunc():

a = 20

print(a)

dunc() #结果为:20

作用域:作用域就是作用范围,按照生效范围来看分为全局作用域和局部作用域。

全局作用域:包含内置命名空间和全局命名空间,在整个文件的任何位置都可以使用(遵循从上到下逐行执行);

局部作用域:在函数内部可以使用;

我们可以通过globals()函数来查看全局作用域中的内容,也可以通过locals()来查看局部作用域中的变量和函数信息,具体示例如下:

a = 10

def func():

a = 40

b = 20

def abc():

print("哈哈")

print(a,b) # 这里使用的是局部作用域

print(globals()) #打印全局作用域中的内容

print(locals()) #打印局部作用域中的内容

func()

三,函数的嵌套

1,只要遇见了( )就是函数的调用,如果没有( )就不是函数的调用。

2,函数的执行顺序,具体示例如下:

#函数的嵌套

def fun2():

print(222)

def fun3():

print(666)

print(444)

fun3()

print(888)

print(33)

fun2()

print(555)

# 结果为:

# 33

# 222

# 444

# 666

# 888

# 555

四、关键字global和nonlocal

现在我们写这样一个代码,首先在全局声明一个变量,然后在局部调用这个变量,并改变这个变量的值,具体如下:

 a = 10

def func():

global a # 这里用的a是全局的

a = 20

print(a)

func()

print(a) # 结果为:20 20

def func():

global a #加global 表示不在局部创建这个变量,而是直接使用全局的a

# 若不存在全局变量a,则创建一个全局变量a

a = 28

print(a)

func()

print(a) # 结果为:28 28

global:

  1,声明一个全局变量;

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

def func():

global a

a = 3

func()

print(a) # 结果为:3

count = 1

def search():

global count

count = 2

search()

print(count) # 结果为:2

注意:对可变数据类型(list,dict,set)可以直接引用,不用通过global也能改变。具体如下:

 li = [1,2,3]

dic = {'a':'b'}

def change():

li.append('a')

dic['q'] = 'g'

print(dic)

print(li)

change()

print(li)

print(dic)

# 结果为:

# {'a': 'b', 'q': 'g'}

# [1, 2, 3, 'a']

# [1, 2, 3, 'a']

# {'a': 'b', 'q': 'g'}

nonlocal :

  1,不能修改全局变量;

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

 a = 10

def func1():

a = 20

def func2():

nonlocal a

a = 30

print(a)

func2()

print(a)

func1()

# 结果:

# 加了nonlocal

# 30

# 30

# 不加nonlocal

# 30

# 20

练习,如果嵌套了很多层,会是一种什么效果,分析明白,那么作用域,global ,nonlocal 就没问题了:

a = 1

def fun_1():

a = 2

def fun_2():

nonlocal a

a = 3

def fun_3():

a = 4

print(a)

print(a)

fun_3()

print(a)

print(a)

fun_2()

print(a)

print(a)

fun_1()

print(a)

# 结果:

# 1

# 2

# 3

# 4

# 3

# 3



以上是 python-函数进阶-动态传参,名称空间,作用域的问题 的全部内容, 来源链接: utcz.com/z/389139.html

回到顶部