似乎无法将带有非字符串关键字的dicts传递给Python中的函数。 (我看到这是在here)
之前提出来的然而,在对我的问题提出某种复杂的解决方案之前,我想我会问专家,看看是否有我遗漏的东西。 不幸的是,如果没有重要的重新分解,我无法轻易改变这种范式,因为之前的作者从未预料到这种类型的行为(这是一个非常简单的例子)。
我有一个名为services
的对象可以对nodes
执行操作。有些nodes
需要不同的service
配置。我每个service
都有一个实例,而不是每个node
的{{1}}个实例,然后我会根据每个service
的配置参数进行组合。 node
及其相应的配置参数存储在service
。
dict
及其node
及其相应的配置参数都会传递给函数(services
),然后处理所有内容。此函数必须能够调用属于setupServices
对象的函数。不幸的是,这失败了错误:
service
如果您想知道将TypeError: setupServices() keywords must be strings
传递给**nodeServices
的是什么,而不仅仅是nodeServices
,那么它就是下面的代码段(在这种情况下,值将是nodeServices
)。我犹豫是否要将此代码专用于个案,因为它充当了许多其他事物的支柱。
if type( value ) is list:
result = f( *value )
elif type( value ) is dict:
result = f( **value )
else:
result = f( value )
results[ name ] = result
return result
还有其他方法可以通过最少的修改来实现这一目标吗?
"A node can be associated with many services"
class Node(object):
pass
"""Setup services routine (outside of the node due to an existing design choice)
I could rewrite, but this would go against the existing author's paradigms"""
def setupServices ( node, **nodeServices ):
for object, objOverrides in nodeServices.items():
"do something with the service object"
"2 simple services that can be perform actions on nodes"
class serviceA(object):
pass
class serviceB(object):
pass
"instantiate an object of each service"
a = serviceA()
b = serviceB()
"Create a node, assign it two services with override flags"
node = Node()
nodeServices = {}
nodeServices[a] = { 'opt1' : True }
nodeServices[b] = { 'opt2' : False }
"Pass the node, and the node's services for setup"
setupServices ( node, **nodeServices )
答案 0 :(得分:2)
更改它的最简单方法是更改setupServices
,使其不再接受关键字参数,而只接受选项的字典。也就是说,将其定义更改为:
def setupServices (node, nodeServices):
(删除**
)。然后,您可以使用setupServices(node, nodeServices)
调用它。
唯一的缺点是你必须传入一个dict,并且不能传递文字关键字参数。使用关键字参数设置,您可以调用setupServices(node, opt1=True)
,但没有关键字参数,如果您想指定该选项“内联”,则必须执行setupServices(node, {'opt1': True})
,传入文字字典。但是,如果你总是以编程方式创建一个选项词典,然后用**
传递它,那么这个缺点并不重要。只有当你实际上有代码传递像setupServices(node, foo=bar)
这样的文字关键字参数时才重要。
正如你所链接的问题中的答案所说,没有办法让函数接受非字符串关键字参数。因此,当foo(**nodeServices)
的键不是字符串时,您无法使nodeServices
工作。 (鉴于此,有点难以理解这个方案是如何工作的,因为在你的例子中,似乎setupServices
总是期待一个dict,其键是服务对象,这意味着将它们作为关键字参数传递永远不会已经工作了。)