15.4-default的本质

作者: BeautifulSoulpy | 来源:发表于2019-09-18 17:05 被阅读0次

    学习的敌人是自己的满足,要认真学习一点东西,必须从不自满开始。对自己,“学而不厌”,对人家,“诲人不倦”;


    函数的复用非常重要,一套定义只需要定义一次;

    在传参数、使用函数的时候,对引用类型一定要小心;

    本章总结:

    函数默认值中,可变类型与不可变类型的引用是 不同的;

    1. 可变类型list,set等 函数的默认值是可以多次复用的;(引用类型与非引用类型的区别), 默认引用类型,引用类型的元素变动,并不是元组的变化;
    2. 默认值参数只初始化一次
    3. print(bar.defaults) 与顺序相关;
      print(bar.kwdefaults) 与字典相关;
    4. 缺省值是函数对象本身的特殊属性,它是放在函数对象上的,函数对象是跟函数定义相关,函数标识符在内存中就关联到函数定义中去了;
    5. 影子拷贝可以防止 引用类型的复用的;看看是不是你想要的结果;

    1.函数默认值的本质

    下面重点介绍默认值参数的坑,虽然说是两个坑,但实际上是一个意思。
    ————使用可变类型作为默认值,就有可能修改这个默认值;(你需要看看这些变量是否会变化!)

    1.1 默认值参数的值是在函数定义时确定的
    默认值参数只初始化一次
    def foo(xyz=[1]):    #默认值参数只初始化一次
        xyz += [1]
        print(xyz)
    foo()
    foo()
    ------------------
    [1, 1]
    [1, 1, 1]
    
    传入值每次都重新传入,调用函数;
    def foo(xyz=[1]):
        xyz += [1]
        print(xyz)
    foo([1])
    foo([1])
    foo([1])
    ----------------------
    [1, 1]
    [1, 1]
    [1, 1]
    
    
    1.2 默认值参数只初始化一次

    如果参数的默认值是数字、字符串、元组或其他不可变类型的数据,并不会有什么影响,但是如果参数的默认值是列表、字典、集合等可变类型数据的话,这里有个大坑。

    可变类型list,set等 的默认值是可以复用的;

    可变类型与不可变类型变量的默认值区别:
    def foo(xyz=[1]):
        #xyz = bar.__defaults__
        xyz += [1]  # xyz = xyz +1
        print(xyz)
        
    def bar(xyz=1):
        #xyz = foo.__defaults__   # [1,1]
        xyz += 1
        print(xyz)
    bar()
    bar()
    bar()
    print(bar.__defaults__)     #查看函数对象缺省值;
    print(foo.__defaults__)
    -------------------------------------------------
    2
    2
    2
    (1,)
    ([1],)
    
    
    可变类型的默认值是可以复用的;
    >>> def demo(newitem, old_list=[]):
                old_list.append(newitem)
                return old_list
    
    >>> print(demo('5', [1, 2, 3, 4]))
    [1, 2, 3, 4, '5']
    >>> print(demo('aaa', ['a', 'b']))
    ['a', 'b', 'aaa']
    >>> print(demo('a'))
    ['a']
    >>> print(demo('b')) #注意这里的输出结果
    ['a', 'b']
    
    
    如果想得到正确结果,建议把函数写成下面的样子:
    def demo(newitem, old_list=None):
        if old_list is None:
            old_list = []    # old_list=[:]
        old_list.append(newitem)
        return old_list
    
    例子1:
    def foo(xyz=None,u='abc',z=123):
        if xyz is None:
            xyz = []
        xyz.append(1)
        print(xyz)
    foo()
    print(foo.__defaults__)
    foo()
    print(foo.__defaults__)
    foo([10])
    print(foo.__defaults__)
    foo([10,5])
    print(foo.__defaults__)
    -------------------------------------------
    [1]
    (None, 'abc', 123)
    [1]
    (None, 'abc', 123)
    [10, 1]
    (None, 'abc', 123)
    [10, 5, 1]
    (None, 'abc', 123)
    
    

    定义函数默认的形式

    1. 函数默认的定义形式(最复杂的形式):
    def bar(xyz,a=2, b='abc', c=(4,), *args, m=5, n=[],**kwargs):   # m,n为kwargs
        pass
    print(bar.__defaults__)
    print(bar.__kwdefaults__)    # 关键字参数**kwargs缺省值给 前面的m,n 关键字;
    -----------------------------------------------
    (2, 'abc', (4,))
    {'m': 5, 'n': []}
    
    
    可变类型复用的常见形式;
    def foo(w,u = 'abc', *, z=123, zz=[456]):
        u = 'xyz'
        z = 789
        zz.append(1)
        print(w,u,z,zz)
    print(foo.__defaults__)
    foo('mageedu')
    foo('mageedu')
    print(foo.__kwdefaults__)
    ------------------------------------------------
    ('abc',)
    mageedu xyz 789 [456, 1]
    mageedu xyz 789 [456, 1, 1]
    {'z': 123, 'zz': [456, 1, 1]}
    

    函数默认值的作用域

    防止可变类型的复用;
    def foo(xyz=[],u = 'abc', z=123):
        xyz = xyz[:]
        xyz.append(1)
        print(xyz)
    foo()
    print(foo.__defaults__)
    foo()
    foo()
    print(foo.__defaults__)
    --------------------------------------------
    [1]
    ([], 'abc', 123)
    [1]
    [1]
    ([], 'abc', 123)
    
    
     函数定义小技巧:不会把内容写死;既可以做复用,也可以做不可变类型;
    def foo(xyz=None, u='abc', z=123):
        if xyz is None:
            xyz = []
        xyz.append(1)
        print(xyz)
        return xyz
    
    foo()
    foo()
    print(foo.__defaults__)
    foo([10])
    print(foo.__defaults__)
    d = foo([10,5])         # [10 , 5 ,1]
    print(foo.__defaults__)
    foo(d)    #[10 , 5 ,1, 1]
    --------------------------------------------
    [1]
    [1]
    (None, 'abc', 123)
    [10, 1]
    (None, 'abc', 123)
    [10, 5, 1]
    (None, 'abc', 123)
    [10, 5, 1, 1]
    [10, 5, 1, 1]
    
    
    

    2.重要的函数属性

    __ 是两个字符(注意)双下划线;
    _doc返回指定函数的文档字符串。
    _name
    返回函数名字。
    _module_返回函数定义所在模块的名字。
    func._defaults返回一个包含默认参数值的元组。
    func._globals返回一个包含函数全局变量的字典引用。
    func._dict返回支持任意函数属性的命名空间。
    func._closure返回一个胞体元组,其中胞体包含了函数自由变量的绑定。

    def foo(xyz=[1]):
        xyz += [1]
        print(xyz)
    foo()
    print(foo.__defaults__)
    -----------------------------
    [1, 1]
    ([1, 1],)
    

    相关文章

      网友评论

        本文标题:15.4-default的本质

        本文链接:https://www.haomeiwen.com/subject/ksukuctx.html