给定一个**kwargs
的函数,我想为这些关键字参数动态设置默认值。是否可以在Python 2.7和Python 3中实现?
在代码中,我希望set_kw_defaults
:
def f(**kwargs):
print kwargs
# in practice, much complicated black-box processing happens
# here; printing the kwargs is just an example
set_kw_defaults(f, {'magic': 'is possible'})
f()
打印:
{'magic': 'is possible'}
我知道如何为位置参数完成这种动态arg-default重写,对于Python 3 / PEP 3102"仅限关键字"参数。我也知道如何构建装饰器来包装f
并拦截/修改kwargs。那个不是我想要的东西。我想为f
定义时未设想的任意kwargs设置默认值,我无法装饰f
。有了这些限制,set_kw_defaults
可能吗?
澄清:f
不是我可以修改源代码或装饰的函数。无论好坏,它已经将其参数作为**kwargs
。这不是通过问题的正常论据,而是一个古怪的异常值。我正在寻找那些了解Python参数传递内部的人的帮助。
Clarification re decoration:我无法装饰或包装f
,因为装饰和包装会创建一个新对象(称为f2
),它被称为原始f
的代理。无论是使用@decorator
语法,简单的功能包装还是基于类的方案,它们都归结为:
def f2(**kwargs):
kwargs.setdefault('color', 'green')
f(**kwargs)
但是如果正在运行的系统的其他部分已经指向f
,那么它们将不受我创建f2
的影响。如果是位置参数或kw-only参数,我需要更改默认值,我可以在原始f
对象中执行此操作,f
的所有用户都将获得新的默认值。如果我装饰,情况并非如此。
答案 0 :(得分:1)
我开始相信这不能用Python完成。
我推断如果为普通位置参数存储默认值(并且在Python 3中,对于仅关键字参数),函数定义可能具有存储这些映射的内部字典。该命令可能适合修改。
但它看起来并不那么简单。在Python 2中,尽管具有默认值的参数看起来像kwarg值,但它们并不是真的。默认值存储在与位置参数匹配的元组中。通过dis.dis
反汇编,我发现对这些位置参数的引用非常深入地嵌入到字节码中,即使存在默认值也是如此。
在Python 3中,情况略好一些,因为只有"关键字"参数和默认值确实存储为dict。这个词是可以修改的。这是成功的一小部分。 但修改kwargs的值,这些kwargs不是预先知道的仅关键字变量不起作用;那些"额外"值被忽略。
长话短说,默认值通常不会以可修改的dict形式存储,并且它们存储在可修改的dict中的唯一情况似乎不足以实现"默认值Monkey修补& #34;我希望如此。
有几位受访者建议修改原始源代码(此处不可能)或修改功能/添加一个前端代理,以便使用kwarg参数。虽然在许多情况下这是完全正确的,但我正在集成到复杂的现有应用程序中意味着我必须搜索预先存在的Python对象空间以获取对原始函数的引用,并将其替换为对代理的引用。在某些情况下,这种详尽的搜索可能是可能的,但在一般情况下似乎有点冒险。查找对f
的一些现有引用并将其替换为f2
的引用可能很有用,但我不知道如何对所有可能的引用进行处理。它可能还需要大量的内存遍历。另一种侵入式方法可能是动态重写字节码。理论上它可能有用......但我对它没有信心。
因为Python的函数默认参数似乎不适合我所讨论的动态设置类型,即使在对字节码,反汇编程序,inspect
模块和其他地方进行重大调整之后也是如此,我要宣布这个"无法完成"然后继续前进。
感谢大家的讨论和想法。