[英]Pythonic way to overwrite a default argument with **kwargs?
With a function f
calling another well-known function in Python (eg a matplotlib
function), what is the most pythonic/efficient/elegant way to define some default values while still giving the possibility to the user of f
to fully customize the called function (typically with **kwargs
), including to overwrite the default keyword arguments defined in f
?使用函数
f
调用 Python 中的另一个众所周知的函数(例如matplotlib
函数),定义一些默认值的最 Pythonic/高效/优雅的方式是什么,同时仍然为f
的用户提供了完全自定义被调用函数的可能性(通常使用**kwargs
),包括覆盖f
中定义的默认关键字参数?
import numpy as np
import matplotlib.pyplot as plt
v = np.linspace(-10.,10.,100)
x,y = np.meshgrid(v, v)
z = -np.hypot(x, y)
def f(ax, n=12, **kwargs):
ax.contourf(x, y, z, n, cmap=plt.cm.autumn, **kwargs)
fig, ((ax0, ax1), (ax2, ax3)) = plt.subplots(2, 2)
f(ax0) # OK
f(ax1, n=100) # OK
f(ax2, n=100, **{'vmax': -2, 'alpha': 0.2}) # OK
# f(ax3, n=100, **{'cmap': plt.cm.cool}) # ERROR
plt.show()
Here, the last call to f
throws:在这里,对
f
的最后一次调用抛出:
TypeError: contourf() got multiple values for keyword argument 'cmap'
TypeError:contourf() 为关键字参数“cmap”获取了多个值
In your wrapper, you could simply adjust kwargs
before passing it to wrapped function:在您的包装器中,您可以在将
kwargs
传递给包装函数之前简单地调整它:
def f(ax, n=12, **kwargs):
kwargs.setdefault('cmap', plt.cm.autumn)
ax.contourf(x, y, z, n, **kwargs)
setdefault
will avoid changing the argument if it was passed to your wrapper, but you could just as easily always clobber it if you wanted.如果将参数传递给您的包装器,
setdefault
将避免更改参数,但如果您愿意,您可以随时轻松地破坏它。
The following minimal example illustrates the options you have when coding this from scratch.以下最小示例说明了从头开始编码时的选项。 Here you can also define a default argument when defining the inner function but NOT specify it when calling it in the wrapper.
在这里,您还可以在定义内部函数时定义一个默认参数,但在包装器中调用它时不要指定它。 Note that default variable a is removed from kwargs within the function, if it was already defined as a default argument.
请注意,默认变量 a 已从函数内的 kwargs 中删除,如果它已被定义为默认参数。 Only in run_test_working3 (setting the default value merely with setdefault in the wrapper) default variable a is not removed from kwargs.
仅在 run_test_working3 中(仅在包装器中使用 setdefault 设置默认值)默认变量 a 不会从 kwargs 中删除。 This might be important if you want to pass kwargs to inner functions within the test function.
如果您想将 kwargs 传递给测试函数中的内部函数,这可能很重要。
kwargs = {"a": 1,
"b": 2,
"c": 3}
kwargs2 = {"b": 2,
"c": 3}
def test(required_arg, a="default", **kwargs):
print(required_arg)
print(a)
print(kwargs)
def test2(required_arg, **kwargs):
print(required_arg)
print(kwargs)
#Set default for a in definition of test but not when calling it in wrapper
# a is removed from kwargs
def run_test_working1(required_arg, **kwargs):
test(required_arg, **kwargs)
#Set default for a different from definition of test in wrapper
# a is removed from kwargs
def run_test_working2(required_arg, **kwargs):
kwargs.setdefault("a", "default2")
test(required_arg, **kwargs)
#Set default value only via setdefault in wrapper
#a is not removed from kwargs
def run_test_working3(required_arg, **kwargs):
kwargs.setdefault("a", "default2")
test2(required_arg, **kwargs)
#Provoke TypeError: test() got multiple values for keyword argument 'a'
def run_test_not_working(required_arg, **kwargs):
test(required_arg, a="default", **kwargs)
print("Demo run_test_working1\n")
run_test_working1("required_arg",**kwargs)
print("\n")
run_test_working1("required_arg",**kwargs2)
print("\n")
print("Demo run_test_working2\n")
run_test_working2("required_arg",**kwargs)
print("\n")
run_test_working2("required_arg",**kwargs2)
print("\n")
print("Demo run_test_working3\n")
run_test_working3("required_arg",**kwargs)
print("\n")
run_test_working3("required_arg",**kwargs2)
print("\n")
print("Demo run_test_not_working\n")
run_test_not_working("required_arg",**kwargs)
print("\n")
test("required_arg")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.