[英]Use an object (e.g., an Enum) as a key in **kwargs?
来自Python新手的一个非常简单的问题:
我的理解是,字典中的键几乎可以是任何不可变的数据类型。 是否可以将不可变的对象(例如,枚举类的成员)作为** 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
。
你在做:
func(MyEnum.X = 1)
在这里,问题是MyEnum.X = 1
您的关键字( MyEnum.X
)实际上是一个表达式( getattr(MyEnum, 'X')
),表达式不能用作函数调用中的关键字。 实际上,只有标识符可以用作关键字。
为了开始工作,您需要使用字典解压缩,如下所示:
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'
由于关键字参数的处理方式,这将不起作用。 该文件说:
[...]接下来,对于每个关键字参数,使用标识符来确定相应的槽(如果标识符与第一个形式参数名称相同,则使用第一个槽,依此类推)[...]
因此,必须有一种方法可以将字典中的键与形式参数名称进行匹配。 例外:
关键字必须是字符串
当您尝试传递非字符串的内容时:
func(**{MyEnum.X: 1})
建议需要最简单的情况:键必须是字符串。
一种可能的解决方法是使隐式的事情变得明确:只需创建一个类,其中包含要传递给属性并传递的所有必要信息。 该代码肯定会更具可读性。
我最初的问题的答案确实是“否”。 但是,由于有了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
(没有错误)
我发现的另一种选择是将字典传递给*args
而不是**kwargs
,或者直接将字典分配给kwargs[0]
:
func({MyEnum.X: 1})
func(kwargs = {MyEnum.X: 1})
(无错误产生)
但是,我真的不喜欢这两种方法。
编辑:请参阅第二个答案,以获得更好的解决方案。
您是否真的想创建一个MyEnum实例?
myenum = MyEnum()
func(myenum.X = 1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.