找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 1769|回复: 0

python中拆包操作的详解(*和**操作符)

[复制链接]

881

主题

0

回帖

2723

积分

管理员

积分
2723
发表于 2023-12-4 10:00:45 | 显示全部楼层 |阅读模式
PEP448 额外的拆包概念

这个PEP提出了*的可迭代拆包操作和**字典拆包操作的延伸用法,以允许在更多的位置、任意的(arbitrary )次数和其他情况(circumstances)下进行拆包。具体来说,在函数调用、理解和生成器表达式以及显示中。

函数调用被提出支持任意次数的的拆包,而不仅仅只进行一次:

<p><pre>    <code class="prism language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token number">1</span> <span class="token number">2</span> <span class="token number">3</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token builtin">dict</span><span class="token punctuation">(</span><span class="token operator">**</span><span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span> y<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token operator">**</span><span class="token punctuation">{</span><span class="token string">&#39;z&#39;</span><span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">&#39;y&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">&#39;z&#39;</span><span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span>
</code></pre></p>
拆包操作被提出在元组、列表、集合和字典形式内允许。

<p><pre>    <code class="prism language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token operator">*</span><span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">4</span>
<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">[</span><span class="token operator">*</span><span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token operator">*</span><span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">**</span><span class="token punctuation">{</span><span class="token string">&#39;y&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">&#39;y&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span>
</code></pre></p>
在字典中,对于相同的键,其后面对应的值会覆盖(override)之前对应的值

<p><pre>    <code class="prism language-python"><span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token operator">**</span><span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token operator">**</span><span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">}</span>
<span class="token punctuation">{</span><span class="token string">&#39;x&#39;</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">}</span>
</code></pre></p>
这个PEP不包括在列表推导式、字典推导式和集合推导式内的拆包操作,尽管这并没有在未来的提案中被排除(rule out)。 基本原理(Rationale)

目前使用的*可迭代拆包操作符具有不必要的限制,会损害可读性。

多次拆包有一个明显的道理。当你想将多个迭代函数解包到一个函数定义中,或者在解包之后加入更多的位置参数时,最自然的方法就是写:

<p><pre>    <code class="prism language-python">function<span class="token punctuation">(</span><span class="token operator">**</span>kw_arguments<span class="token punctuation">,</span> <span class="token operator">**</span>more_arguments<span class="token punctuation">)</span>
function<span class="token punctuation">(</span><span class="token operator">*</span>arguments<span class="token punctuation">,</span> argument<span class="token punctuation">)</span>
</code></pre></p>
它极大地简化了 类型的加法操作,如合并字典,并以一种明确和定义良好的方式进行。

combination = {**first_dictionary, “x”: 1, “y”: 2}

instead of:

combination = first_dictionary.copy()

combination.update({“x”: 1, “y”: 2})

在喜欢使用表达式的情况下,这一点尤为重要。这也很有用,因为它是将迭代数加总到一个列表中的一种更易读的方式,比如my_list + list(my_tuple) + list(my_range),现在只相当于[*my_list, *my_tuple, *my_range]。

规范(Specification)

函数调用可以接受数量不受限制的和**解包。对位置参数相对于解包的顺序没有限制,对关键字参数相对于**解包的顺序也没有限制。

函数调用继续遵守关键词参数必须跟随位置参数的规范,即字典拆包必须跟随可迭代拆包之后。

目前,如果一个参数被多次给出–比如一个位置参数既通过位置又通过关键字给出–就会引发TypeError。对于通过多次**解包提供的重复参数这种错误仍然存在,例如 f(**{‘x’: 2}, **{‘x’: 3})。

Tuples、list、set和dictionary将允许解包。这就好比在解包的地方按顺序插入了来自解包项的元素,就像在函数调用中的解包一样。字典需要**解包,其他的都需要*解包。

字典中的键按从右到左的优先级顺序排列,所以{**{‘a’: 1}, ‘a’: 2, **{‘a’: 3}}评价为{‘a’: 3}。对解包的数量和位置没有限制。

缺点(Disadvantage)

函数调用中参数的允许顺序比以前复杂了。对这些规则最简单的解释可能是 “位置参数先于关键字参数和解包;*解包先于解包”。

而∗elements,=iterable*elements, = iterable∗elements,=iterable会导致元素是一个列表,elements=∗iterable,elements = *iterable,elements=∗iterable,会导致元素是一个元组。这样做的原因可能会让不熟悉该结构的人感到困惑。

有人对字典中的重复键被允许,但在函数调用语法中的重复键会引起错误的意外差异表示担忧。虽然目前的语法已经存在这种情况,但这个建议可能会加剧这个问题。这个问题在实践中到底有多大,还有待观察。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|掌设笔电 ( 京ICP备18032618号-3|京ICP备18032618号-3 )

GMT+8, 2025-6-8 06:52 , Processed in 0.033750 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表