简体   繁体   English

用 **kwargs 覆盖默认参数的 Pythonic 方法?

[英]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.

相关问题 处理默认 arguments 和参数覆盖许多命名参数的 Pythonic 方法? - Pythonic way to handle default arguments and argument overwrite with many named parameters? 设计 class 的 Pythonic 方法,它具有可以被 kwargs 覆盖的默认数据成员 - Pythonic way to design class which has default data members which can be overridden by kwargs 检查变量是否作为 kwargs 传递的 Pythonic 方法? - Pythonic way to check if a variable was passed as kwargs? 在此函数中传递kwargs的最pythonic方法是什么? - What is the most pythonic way to pass kwargs in this function? 是否有一种 pythonic 的方式来根据 function 中的 kwargs 来控制流量? - Is there a pythonic way to control the flow depending on kwargs in a function? 使用空字典作为默认参数的最Pythonic方法是什么? - What is the most Pythonic way to use an empty dictionary as a default argument? 设置默认值的Python方式 - Pythonic way of setting a default 扩展kwarg时使用Python方式广播/循环遍历值 - Pythonic way to broadcast/loop through values when expanding kwargs 从 **kwargs 实例化多个对象的 pythonic 方法是什么? - What's the pythonic way to instantiate multiple objects from **kwargs? Pythonic方法检查kwargs中的所有值是否为字符串“false” - Pythonic way of checking if all values in kwargs are the string “false”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM