通过元类修复可变的默认参数

时间:2016-05-03 22:46:07

标签: python decorator mutable metaclass default-arguments

issue with mutable argument default values在Python中非常有名。基本上可变的默认值在定义时分配一次,然后可以在函数体中修改,这可能会让人感到惊讶。

今天在工作中我们正在考虑处理这个的不同方法(在针对None的测试旁边显然是正确的方式......)我想出了一个{ {1}}您可以找到 here 下面的解决方案(它只有几行,因此要点可能更具可读性)

它基本上是这样的:

  1. 对于每个函数obj。在属性dict。
  2. 可变默认参数的内省函数。
  3. 如果是可变的默认args。找到,用装饰函数替换函数
  4. 装饰函数是使用一个注册默认arg的闭包创建的。名称和初始默认值
  5. 在每个函数调用中,检查是否有kwarg。通过注册名称给出,如果给出了 NOT ,则重新设置初始值以创建浅层副本并在执行前将其添加到kwargs。
  6. 现在的问题是这种方法适用于Metaclasslist个对象,但它在某种程度上无法用于其他可变的默认值,如dictset()任何想法为什么?
    随意测试此代码。唯一的非标准dep。是六(pip安装六)所以它在Py2和3中工作。

    bytearray()

1 个答案:

答案 0 :(得分:3)

您现在的代码实际上是按照您的期望进行的。调用时,将默认值的新副本传递给函数。但是,由于您对此新值不执行任何操作,因此在下次调用时垃圾收集并且内存可以立即重新分配

因此,你不断得到id()

不同时间点的两个对象的id()相同的事实并不表示它们是同一个对象。

要查看此效果,请更改您的功能,以便使用会增加其引用计数的值执行某些操作,例如:

class ImmutableDefaultArgumentsObject(ImmutableDefaultArgumentsBase):
    cache = []
    def function_a(self, mutable_default_arg=set()):
        print("function_b", mutable_default_arg, id(mutable_default_arg))
        self.cache.append(mutable_default_arg)

现在运行代码将提供:

function_b set() 4362897448
function_b set() 4362896776
function_b set() 4362898344
function_b set() 4362899240
function_b set() 4362897672