Python:函数默认值的作用域【

您所在的位置:网站首页 python中函数的作用是什么 Python:函数默认值的作用域【

Python:函数默认值的作用域【

2023-09-07 06:05| 来源: 网络整理| 查看: 265

例子:引入

def foo(abc=[]): abc.append(200) print(abc) foo() foo() 结果: [200] [200, 200]

第二次调用为什么问什么打印的是[ 200,200],而不是[ 200 ]?

因为函数即对象,python把函数的默认值放在了属性中,这个属性就伴随着这个函数对象的 整个生命周期,和abc这个变量没有关系,abc调用玩就消失了可查看foo.__defaults__属性查看

例子:函数值的默认值是可变类型的 : [  ]

 

def foo(abc=[],d = 1,e=2): abc.append(200) print(abc) print(foo(),id(foo)) print(foo.__defaults__) print(foo(),id(foo)) print(foo.__defaults__) 结果: [200] #函数结果 None 24057800 #函数id ([200], 1, 2) #函数默认值属性 [200, 200] #函数结果 None 24057800 #函数ID ([200, 200], 1, 2) #函数默认值属性 我们发现函数的对象ID,并没有变化,说明这个对象没有变函数的默认值属性__defaults__是用元组保存的abc的默认值是可变类型 [ ],这里的变动只是默认值可变类型的该表,而不是整个元组的改变

例子:默认值非可变类型:常量

 

def foo(a,d = 1,e=2): d = 3 e = 4 print(a,d,e) print(foo.__defaults__) foo("123") print(foo.__defaults__) 结果: (1, 2) #函数的默认值 123 3 4 #函数的结果 (1, 2) #函数的默认值

函数中重新定义的默认值的数值,只是重新赋值,并不会改变函数的默认值,#函数的默认值是元组类型,也不会被改变的

简单来讲就是:函数属性__defaults__中使用元组保存所有位置参数默认值,它不会因为在函数体内使用了它而发生改变

 例子:__kwdefaults__中使用字典保存所有keyword-only参数的默认值

def foo(a, b='abc', *, c=1, d=[]): b = 'xyz' c = 789 d.append(1) print(a, b, c, d) print(foo.__defaults__) foo('abc') print(foo.__kwdefaults__) 结果: ('abc',) # * 之前的默认值参数都是元组 abc xyz 789 [1] #函数结果 {'c': 1, 'd': [1]} # keyword-only形式的默认值参数 属性__defaults__中使用元组保存所有位置参数默认值属性__kwdefaults__中使用字典保存所有keyword-only参数的默认值

默认的作用域有什么用?

使用可变类型作为默认值,就可能修改这个默认值有时候这个特性是好的,有的时候这种特性是不好的,有副作用如何做到按需改变呢?看下面的2种方法

方法一:可变数据类型:对引入的参数做影子拷贝,生成新的列表  【对原参数进行拷贝】

def foo(abc=[]): abc = abc[:] abc.append(200) print(abc) foo() print(1,foo.__defaults__) foo() print(2,foo.__defaults__) foo([100]) print(3,foo.__defaults__) foo([300]) print(4,foo.__defaults__) lis = [1,2] foo(lis) print(lis) 结果: [200] #结果 1 ([],) #参数默认的值属性 [200] #生成的结果 2 ([],) #参数的默认值属性 [100, 200] #参数传参后的列表结果 3 ([],) #参数的默认值属性 [300, 200] #参数传参后的列表结果 4 ([],) #参数的默认值属性 [1,2,200] #函数结果 [1,2] #传入的参数列表 通过上述函数:只是对函数的参数或者默认参数的副本,进行的拷贝,并不能改变元参数,

方法二:使用不可变类型的默认值   【对原参数结果改变】

def foo(abc=None): if abc == None: abc=[] abc.append(200) return abc lis = [1,2] b = foo(lis) print(b) print(foo.__defaults__) 结果: [1, 2, 200] #函数结果 (None,) #函数的缺省值 如果使用缺省值None就创建一个列表如果传入一个列表,就修改这个列表

总结:

第一种方法

使用影子拷贝创建一个新的对象,永远不能改变传入的参数

第二种方法

通过值的判断就可以灵活的选择创建或者修改传入对象这种方式灵活,应用广泛很多函数的定义,都可以看到使用None这个不可变的值作为默认参数,可以说这是一种惯用法


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3