使用对象(例如,枚举)作为** kwargs中的键?

时间:2014-10-28 18:08:44

标签: python

来自Python新手的非常简单的问题:

我的理解是dict中的键可以是任何不可变数据类型。是否可以将不可变对象(例如,枚举类的成员)作为函数或类的** kwargs字典中的键传递?我试过了,答案似乎是"没有":

from enum import Enum
class MyEnum(Enum):
    X= 'X'
    Y= 'Y'
def func(*args,**kwargs):
    pass
func(MyEnum.X = 1)

输出:

"SyntaxError: keyword can't be an expression"

但是,我可能会遗漏一些东西。

编辑:请注意,我并不是要使密钥等于MyEnum.X.value(在这种情况下是一个字符串);我希望密钥是实际的Enum对象,例如MyEnum.X

5 个答案:

答案 0 :(得分:1)

你在做:

func(MyEnum.X = 1)

此处问题是MyEnum.X = 1 - 您的关键字(MyEnum.X)实际上是一个表达式(getattr(MyEnum, 'X')),并且表达式不能在函数调用中用作关键字。实际上,只有identifiers可以用作关键字。

要让您的通话工作,您需要使用字典解压缩:

func(**{MyEnum.X.name: 1})

注意,要获取属性的名称,我需要执行MyEnum.X.nameMyEnum.X.value,具体取决于您设置枚举的方式 - 在您的情况下,我们是相同的。

>>> from enum import Enum
>>> class Foo(Enum):
...   X = 'X'
... 
>>> Foo.X.value
'X'
>>> Foo.X.name
'X'

答案 1 :(得分:1)

由于处理关键字参数的方式,这不会起作用。 The documentation说:

  

[...]接下来,对于每个关键字参数,标识符用于确定相应的槽(如果标识符与第一个形式参数名称相同,则使用第一个槽,依此类推)[。 ..]

因此必须有一种方法可以将字典中的键与形式参数名称进行匹配。例外:

  

关键字必须是字符串

当你试图传递一些不是字符串的东西时:

func(**{MyEnum.X: 1})

建议最简单的情况是:密钥必须是字符串。

一种可能的解决方法是使隐式事物显式化:只需创建一个包含要在其属性中传递的所有必要信息并传递它的类。代码肯定会更具可读性。

答案 2 :(得分:0)

我原来问题的答案确实是"没有"。然而,由于mgilson和BartoszKP等人的意见,我提出的以下工作并不是一个糟糕的解决方案,并解决了我当前的问题。我提供给其他人看看谁试图做类似的事情:

from enum import Enum
class MyEnum(Enum):
    X= 'X'
    Y= 'Y'

def func(*args,**kwargs):
    #replace kwargs with kwargsNew
    kwargsNew = {}
    for kwkey, kwvalue in kwargs.items():
        try: kwargsNew[MyEnum(kwkey)] = kwvalue
        except ValueError: kwargsNew[kwkey] = kwvalue
    doStuffWithKwargs(kwargsNew)

def doStuffWithKwargs(k):
    for K in k:
        print(K)

#Pass the name X or Y as the key; 
#all other keys not found in `MyEnum` are treated normally
func(X = 1, Y = 2, Z = 3)

输出:

Z
MyEnum.X
MyEnum.Y

(没有错误)

答案 3 :(得分:-1)

我找到的一个替代方法是将字典传递到*args而不是**kwargs,或直接将字典分配给kwargs[0]

func({MyEnum.X: 1})
func(kwargs = {MyEnum.X: 1})

(没有产生错误)

但是,我真的不喜欢这两种方法。

编辑:有关更好的解决方案,请参阅my second answer

答案 4 :(得分:-1)

你真的想创建一个Enum实例吗?

 myenum = MyEnum()
 func(myenum.X = 1)