【问题标题】:"ES6-like" Python dict spread [duplicate]“类似ES6”的Python dict传播[重复]
【发布时间】:2019-06-12 22:19:39
【问题描述】:

我正在尝试在 Python 3.6 中编写一个函数 spread(我不能使用任何更新的版本),到目前为止,我已经得到了如下所示的内容:

d = {"a": 1, "b": 2, "c": 3}
a, b, c = spread(d, ['a', 'b', 'c'])
a
>> 1
b
>> 2
c
>> 3

问题是:存在某种重复,因为左侧的位置必须与函数第二个参数上的键列表匹配才能有意义。因此,更改键列表的顺序,变量a 将保存与d['a'] 不同的值。我需要保持一致性

a, b, c = spread(d) # how?

spread(d, ???)。我考虑使用None 初始化a, b, c,然后将它们作为列表传递。

关于如何解决这个问题的任何想法或线索?甚至可能吗? 谢谢!

【问题讨论】:

  • 您能否添加一个示例,说明“spread”在 ES6 中的作用?
  • 为什么不直接访问字典中的值呢?通常不需要像这样污染模块名称空间
  • 使用locals() 实际上是一个非常有趣的线索,感谢@Graipher。我不知道您的回复为何被删除):
  • 这似乎是 javascript 的规范参考:Object destructuring
  • dict 对象并不是 javascript 对象的真正替代品。 dict 对象更像 Javascript Map 对象。如果没有 hacky globals 的东西,你无法在 Python 中实现这一点,而对于本地分配,它需要更多 hacky 的东西。

标签: python


【解决方案1】:

不,这真的不可能。你不能拥有

a, b, c = spread(d)

a, c, b = spread(d)

b 赋予相同的值。这是因为the right side of an assignment statement is evaluated first。所以spread 在你的代码知道你把它们放在左边的顺序之前执行并返回它的值。

一些谷歌搜索导致相信通过“dicts 的类似传播语法”,您正在寻找**dict 语法。见What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

【讨论】:

  • 是的,我也遇到了同样的问题,但不幸的是 ** 不能用于开始操作的右侧):
【解决方案2】:

不是很漂亮,但你可以去那里做:

def f1(a, b, c, **_):
    print(a)
    print(b)
    print(c)

d = {"a": 1, "b": 2, "c": 3}

f1(**d)

非常不同的语义,但发布是希望它能激发一些灵感!

根据@phhu 的评论,f1 定义中的**catch-all keyword argument specifier,告诉Python 所有不匹配的参数都应该放入给定名称的字典中,在我的例子中是_。以f1(**d) 调用表示将指定的字典解包到函数的参数中。

因此如果它被用作:

e = {"a": 1, "b": 2, "c": 3, "extra": 42}

f1(**e)

然后在f1 内部,_ 变量将设置为{"extra": 42}。我使用 _ 是因为此标识符在 a few languages 中使用以指示一次性/占位符变量名称,即预计以后不会使用的东西。

【讨论】:

  • 刚刚意识到这是在其他 cmets 中隐含的……将其作为单独的答案是否有任何目的?
  • 注意(对自己):函数参数中的 **_ 用于吸收字典中的任何其他条目,防止出现“意外的关键字参数”。
  • @phhu 试图解释发生了什么,希望对您有所帮助!
【解决方案3】:

globals().update(d) 按照你的要求做,但是......

  • 它仅在全局范围内有效,locals() 不保证返回可写字典。
  • 它会削弱代码的可调试性。如果以这种方式设置的变量之一以意外值结束,则搜索不会显示这是设置变量的位置。

【讨论】:

  • 谢谢!这是一个很好的线索,我会尝试使用它(:另一个用户之前给了我同样的线索,但不幸的是,他的评论被删除了):
【解决方案4】:

您可以将变量分配给 values() 调用的结果:

>>> d = {"a": 1, "b": 2, "c": 3}
>>> a,b,c = d.values()
>>> a
1
>>> b
2
>>> c
3

我不建议对无法保证 dict 顺序的 Python 版本执行此操作,但幸运的是这应该在 3.6 及更高版本中有效。

【讨论】:

  • 请注意,保证的顺序是 insertion 顺序,或此处文字中定义的顺序。如果你想要一些不同的东西,比如字母顺序,就需要排序
  • 我不会选择这个选项。在我正在工作的上下文中,这是行不通的,因为我永远不能保证上层会在有序字典中保持预期的顺序。感谢您的想法(:
猜你喜欢
  • 2021-08-18
  • 2011-04-30
  • 1970-01-01
  • 2016-05-29
  • 2019-10-02
  • 1970-01-01
  • 2019-04-23
  • 2022-11-13
  • 2016-05-22
相关资源
最近更新 更多