如何用Python的方式使用**kwargs覆盖默认参数?

4

如果在Python中,使用一个函数f调用另一个广为人知的函数(例如matplotlib函数),如何以最Pythonic/高效/优雅的方式定义一些默认值,同时仍然为用户提供完全自定义所调用函数的可能性(通常使用**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()

在这里,对f的最后一次调用抛出异常:

TypeError: contourf()传递了多个值给关键字参数'cmap'

2个回答

10
在您的包装器中,您可以在将其传递给包装函数之前简单地调整kwargs参数:
def f(ax, n=12, **kwargs):
    kwargs.setdefault('cmap', plt.cm.autumn)
    ax.contourf(x, y, z, n, **kwargs)

setdefault会避免改变传递给你的封装器的参数,但是如果你想要,你也可以随时覆盖它。


0

下面的最小示例演示了从头开始编写此代码时您拥有的选项。在这里,您还可以在定义内部函数时定义默认参数,但在调用包装器时不指定它。请注意,在函数内部,如果已将默认变量a定义为默认参数,则会从kwargs中删除它。仅在run_test_working3中(仅使用包装器中的setdefault设置默认值),默认变量a不会从kwargs中删除。如果您想将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")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接