Python 将可变类型作为参数引发的陷阱及解决方案

# 如下函数一,将会出现意外的结果

# 函数一:
class Foo(object):
    def __init__(self, name='', stuff=[]):
         self.name = name
         self.stuff = stuff

    def add_stuff(self, gadget):
        self.stuff.append(gadget)

>>> f = Foo()
>>> f.add_stuff('tree')
>>> f.stuff
['tree']
>>> g = Foo()
>>> g.stuff
['tree']

避免上述陷阱的解决方法:

# 方法一:
class Foo(object):
    def __init__(self, name='', stuff=[]):
        self.name = name
        self.stuff = stuff or []

    def add_stuff(self, gadget):
        self.stuff.append(gadget)


# 方法二:
class Foo(object):
    def __init__(self, name='', stuff=None):
        self.name = name
        if stuff is None: stuff = []
        self.stuff = stuff

    def add_stuff(self, gadget):
         self.stuff.append(gadget)


# 方法三:
class Foo(object):
    def __init__(self, name='', stuff=None):
        self.name = name
        self.stuff = [] if stuff is None else stuff

    def add_stuff(self, gadget):
         self.stuff.append(gadget)


>>> f = Foo()
>>> f.add_stuff('tree')
>>> f.stuff
['tree']
>>> g = Foo()
>>> g.stuff
[]

 

这里需要解释一下,Python函数在定义的时候,默认参数L的值就被计算出来了,即[], 而不是初始化默认值。此时L指向[]。所以如果L中的内容改变了,下次调用引用的内容也就不再是[]了。所以要牢记一点定义默认参数必须指向不可变对象!

官方解释:python中函数的默认参数在定义时确定,而不是每次调用时初始化值,如果不显示的对默认参数赋值,那么使用的是在编译时确定的对象。

参考链接 https://eli.thegreenplace.net/2009/01/16/python-insight-beware-of-mutable-default-values-for-arguments

               https://blog.csdn.net/icaniup/article/details/81142499

 

posted @ 2021-01-14 10:18  向技术致敬  阅读(141)  评论(0)    收藏  举报