来自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
。
答案 0 :(得分:1)
你在做:
func(MyEnum.X = 1)
此处问题是MyEnum.X = 1
- 您的关键字(MyEnum.X
)实际上是一个表达式(getattr(MyEnum, 'X')
),并且表达式不能在函数调用中用作关键字。实际上,只有identifiers可以用作关键字。
要让您的通话工作,您需要使用字典解压缩:
func(**{MyEnum.X.name: 1})
注意,要获取属性的名称,我需要执行MyEnum.X.name
或MyEnum.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)