函数 奇怪的形参

一、函数的默认值参数在定义的时候就已经赋值了,而不是在调用的时候才赋值:

class A:
    def __init__(self):
        print('init')
def f(a=A()):
    pass

 

i = 1
def f(a=i):
    print(a)  # 1  在创建这个函数的时候就已经给a赋值了,并不是在调用函数的时候才给a赋值。所以a是1
    print(i)  # 6  在调用函数的时候此时i的值是6

i = 6
f()

 

二、默认值参数如果是一个可变对象:list set dist 自定义对象等

同理 L=[] 是在定义的时候就赋值了,因为在调用的时候没有重先赋值,所以它就一直引用同一个对象

在调用函数时,如果没有传递默认值参数,就指向默认值对象(就算上次传递了,这次也是指向默认值对象),并且这个默认对象一直不会释放,所以,l 的值就会越来越长

def f(a,L=[]):
    L.append(a)
    print(L)
    

f(1)  # [1]
f(2)  # [1, 2]
f(3)  # [1, 2, 3]

再如:有默认值参数 p 在定义的时候就赋值了,如果你不重先赋值,它就一直引用这个对象

所以,f(1) f(2)应该能够理解

f(3...)重先赋值,所以引用的是新的值

f(4)没有赋值,所有还是引用原来的值

class PP:
    def __init__(self,name,age):
        self.name = name
        self.age = age


def f(a, p=PP('tangjun', 42)):
    p.age += a
    print(p.name, p.age)

f(1)  # tangjun 43
f(2)  # tangjun 45
f(3, PP('xdong', 20))  # xdong 23
f(4)  # tangjun 49

 

三,默认值参数如果是一个可变对象,怎么避免引用同一个对象:

把默认值设置成None,python并不会把None当成一个可变对象

def f(a,L=None):
    if L == None: L = []
    L.append(a)
    print(L)


f(1)  # [1]
f(2)  # [2]
f(3)  # [3]

总结:

函数形参的值在定义函数时就被创建(注意,不是在调用函数时才被创建),且永不改变,除非调用函数时重先给它传递一个参数

参数a:引用了 i 的值:1,但是在调用函数 f() 的时候,虽然 i 的值已经改变,但是a的值不会改变,因为定义的时候就确定了(除非调用函数时给它传一个别的值。)

使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况。如下

参数L :在定义函数的时候引用了一个[],然后每次调用函数都不重先赋值,所以  L 一直引用同一个对象,并且这个对象不停的被添加新的元素,

结论,函数的形参在定义函数时就被赋值了,而不是调用的时候才赋值,准确的说调用的时候是重先赋值(如果传递了实参的话)

思考,以前遇到过想编写一个功能独立的函数,函数在多次调用期间想共享一个变量(全局变量),又不想节外生枝在函数外创建这个全局变量,以破坏函数功能的相对独立性(函数依赖于函数体外的全局变量)。遇到这种情况可以把这个全局变量定义成有默认值的形参就形了。

posted @ 2020-11-11 06:59  老谭爱blog  阅读(77)  评论(0)    收藏  举报