Answers:
您可以将默认值传递给get()
不在字典中的键:
self.val2 = kwargs.get('val2',"default value")
但是,如果计划使用具有特定默认值的特定参数,为什么不首先使用命名参数?
def __init__(self, val2="default value", **kwargs):
__init__()
。有人可以解释为什么这是一个皮棉价值的犯罪吗?
self.__dict__update(**kwargs)
方法可以重新定义方法并导致其他错误
虽然大多数答案都在说,例如,
def f(**kwargs):
foo = kwargs.pop('foo')
bar = kwargs.pop('bar')
...etc...
是相同的”
def f(foo=None, bar=None, **kwargs):
...etc...
这不是真的。在后一种情况下,f
可以称为f(23, 42)
,而前一种情况仅接受命名参数-不能进行位置调用。通常,您想让调用者具有最大的灵活性,因此,如大多数答案所断言的那样,第二种形式是可取的:但这并非总是如此。当您接受许多通常仅传递几个可选参数的可选参数时,强制使用命名参数可能是一个好主意(避免意外和调用代码不可读!)threading.Thread
就是一个例子。第一种形式是如何在Python 2中实现它。
成语是如此重要,以至于在Python 3现在有专门的配套语法:单后每个参数*
的def
签名关键字只,也就是说,不能被作为位置参数传递,但只是作为一个命名的。因此,在Python 3中,您可以将上述代码编写为:
def f(*, foo=None, bar=None, **kwargs):
...etc...
实际上,在Python 3中,您甚至可以具有非可选的仅关键字参数(没有默认值的参数)。
但是,Python 2仍有很长的生产寿命,因此最好不要忘记使您能够在Python 2中实现重要设计思想的技术和习惯用法,而Python 3语言直接支持这些重要设计思想!
我建议像这样
def testFunc( **kwargs ):
options = {
'option1' : 'default_value1',
'option2' : 'default_value2',
'option3' : 'default_value3', }
options.update(kwargs)
print options
testFunc( option1='new_value1', option3='new_value3' )
# {'option2': 'default_value2', 'option3': 'new_value3', 'option1': 'new_value1'}
testFunc( option2='new_value2' )
# {'option1': 'default_value1', 'option3': 'default_value3', 'option2': 'new_value2'}
然后根据需要使用值
dictionaryA.update(dictionaryB)
添加的内容dictionaryB
以dictionaryA
覆盖任何重复的密钥。
for key in options: self.__setattr__(key, options[key])
,我很好。 :)
你会的
self.attribute = kwargs.pop('name', default_value)
要么
self.attribute = kwargs.get('name', default_value)
如果使用pop
,则可以检查是否发送了任何虚假值,并采取适当的措施(如果有)。
.pop
将“帮助您检查是否发送了任何虚假值”来澄清您的意思?
kwargs
是有原因的。
default_value
传递的值?并随后删除该密钥?
使用** kwargs和默认值很容易。但是,有时候,您不应该一开始就使用** kwargs。
在这种情况下,我们并没有真正充分利用** kwargs。
class ExampleClass( object ):
def __init__(self, **kwargs):
self.val = kwargs.get('val',"default1")
self.val2 = kwargs.get('val2',"default2")
以上是“为什么要打扰?” 宣言。与...相同
class ExampleClass( object ):
def __init__(self, val="default1", val2="default2"):
self.val = val
self.val2 = val2
当您使用** kwargs时,意味着关键字不仅是可选的,而且是有条件的。规则比简单的默认值复杂得多。
当您使用** kwargs时,通常意味着类似以下内容,其中简单的默认值不适用。
class ExampleClass( object ):
def __init__(self, **kwargs):
self.val = "default1"
self.val2 = "default2"
if "val" in kwargs:
self.val = kwargs["val"]
self.val2 = 2*self.val
elif "val2" in kwargs:
self.val2 = kwargs["val2"]
self.val = self.val2 / 2
else:
raise TypeError( "must provide val= or val2= parameter values" )
由于**kwargs
在参数个数未知时使用,为什么不这样做呢?
class Exampleclass(object):
def __init__(self, **kwargs):
for k in kwargs.keys():
if k in [acceptable_keys_list]:
self.__setattr__(k, kwargs[k])
这是另一种方法:
def my_func(arg1, arg2, arg3):
... so something ...
kwargs = {'arg1': 'Value One', 'arg2': 'Value Two', 'arg3': 'Value Three'}
# Now you can call the function with kwargs like this:
my_func(**kwargs)
get_form_kwargs()
)。ccbv.co.uk/projects/Django/1.5/django.views.generic.edit/...
get_form()
方法说明了如何通过遵循另一种方法(get_form_kwargs
如上所述)来广泛地获取关键字参数。它实例如下形式:form_class(**self.get_form_kwargs())
。
get_form_kwargs()
在子类视图中进行覆盖,并根据特定的逻辑添加/删除kwarg。但这是针对Django教程的。
@AbhinavGupta和@Steef建议使用update()
,这对处理大型参数列表非常有帮助:
args.update(kwargs)
如果我们要检查用户是否未传递任何虚假/不受支持的参数,该怎么办?@VinaySajip指出,pop()
可以用来迭代处理参数列表。然后,任何剩余的参数都是虚假的。真好
这是执行此操作的另一种可能方法,保留了using的简单语法update()
:
# kwargs = dictionary of user-supplied arguments
# args = dictionary containing default arguments
# Check that user hasn't given spurious arguments
unknown_args = user_args.keys() - default_args.keys()
if unknown_args:
raise TypeError('Unknown arguments: {}'.format(unknown_args))
# Update args to contain user-supplied arguments
args.update(kwargs)
unknown_args
是一个set
包含默认值中不出现的参数名称。
** kwargs可以自由添加任意数量的关键字参数。可能会有一个密钥列表,他可以为其设置默认值。但是,不必为无限数量的键设置默认值。最后,将键作为实例属性可能很重要。因此,我将执行以下操作:
class Person(object):
listed_keys = ['name', 'age']
def __init__(self, **kwargs):
_dict = {}
# Set default values for listed keys
for item in self.listed_keys:
_dict[item] = 'default'
# Update the dictionary with all kwargs
_dict.update(kwargs)
# Have the keys of kwargs as instance attributes
self.__dict__.update(_dict)