我是靠谱客的博主 飘逸香氛,最近开发中收集的这篇文章主要介绍Python:函数默认值的作用域【__defaults__】【__kwdefaults__】,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

例子:引入

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这个不可变的值作为默认参数,可以说这是一种惯用法

最后

以上就是飘逸香氛为你收集整理的Python:函数默认值的作用域【__defaults__】【__kwdefaults__】的全部内容,希望文章能够帮你解决Python:函数默认值的作用域【__defaults__】【__kwdefaults__】所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部