Home > Database > Mysql Tutorial > 1.2.从任意长度的迭代中解压元素

1.2.从任意长度的迭代中解压元素

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Release: 2016-06-07 15:32:56
Original
963 people have browsed it

问题 想从iterable中解压N个元素,但iterable元素可能多于N个,会导致“to many values to unpack”的异常。 解决方法 Python的 表达式(star expression)可被用来解决这个问题。举例,假如你课程并决定在学期结束时放弃最高和最低分,只取剩下的平均分,如

问题

想从iterable中解压N个元素,但iterable元素可能多于N个,会导致“to many values to unpack”的异常。

解决方法

Python的表达式(star expression)可被用来解决这个问题。举例,假如你课程并决定在学期结束时放弃最高和最低分,只取剩下的平均分,如果只有4门课程,你可以简单的加压所有的4门,但是如果有24门课程呢?表达式可以容易的做到:

<span>def</span> <span>drop_first_last</span><span>(</span><span>grades</span><span>):</span>
    <span>first</span><span>,</span> <span>*</span><span>middle</span><span>,</span> <span>last</span> <span>=</span> <span>grades</span>
    <span>return</span> <span>avg</span><span>(</span><span>middle</span><span>)</span>
Copy after login

另一个用例,假如你有包含姓名、电子邮件和电话号码的用户记录,你可以这样加压记录:

<span>>>></span> <span>record</span> <span>=</span> <span>(</span><span>'Dave'</span><span>,</span> <span>'dave@example.com'</span><span>,</span> <span>'773-555-1212'</span><span>,</span> <span>'847-555-1212'</span><span>)</span>
<span>>>></span> <span>name</span><span>,</span> <span>email</span><span>,</span> <span>*</span><span>phone_numbers</span> <span>=</span> <span>user_record</span>
<span>>>></span> <span>name</span>
<span>'Dave'</span>
<span>>>></span> <span>email</span>
<span>'dave@example.com'</span>
<span>>>></span> <span>phone_numbers</span>
<span>[</span><span>'773-555-1212'</span><span>,</span> <span>'847-555-1212'</span><span>]</span>
<span>>>></span>
Copy after login

值得注意的是,变量phone_numbers将永远是个列表,不管解压多少电话号码(包括None),因此任何使用phone_numbers的代码不会考虑是否是列表或者任何额外的类型检查。

*变量也可以在列表的开始。举例,假如你有一个反映公司过去8个季度的销售记录的序列,如果你想看最近一个季度的记录是否比前7个季度的平均值高,你可以这么做:

<span>*</span><span>trailing_qtrs</span><span>,</span> <span>current_qtr</span> <span>=</span> <span>sales_record</span>
<span>trailing_avg</span> <span>=</span> <span>sum</span><span>(</span><span>trailing_qtrs</span><span>)</span> <span>/</span> <span>len</span><span>(</span><span>trailing_qtrs</span><span>)</span>
<span>return</span> <span>avg_comparison</span><span>(</span><span>trailing_avg</span><span>,</span> <span>current_qtr</span><span>)</span>
Copy after login

在Python的解释器里,可以看到以下结果:

<span>>>></span> <span>*</span><span>trailing</span><span>,</span> <span>current</span> <span>=</span> <span>[</span><span>10</span><span>,</span> <span>8</span><span>,</span> <span>7</span><span>,</span> <span>1</span><span>,</span> <span>9</span><span>,</span> <span>5</span><span>,</span> <span>10</span><span>,</span> <span>3</span><span>]</span>
<span>>>></span> <span>trailing</span>
<span>[</span><span>10</span><span>,</span> <span>8</span><span>,</span> <span>7</span><span>,</span> <span>1</span><span>,</span> <span>9</span><span>,</span> <span>5</span><span>,</span> <span>10</span><span>]</span>
<span>>>></span> <span>current</span>
<span>3</span>
Copy after login

讨论

扩展的迭代解包是专为位置或任意长度的迭代序列解包的,通常情况下,这些迭代序列在结构上有已知的组件或者模式(比如数字1后面的会是电话号码)*表达式可以让开发者很容易解压这些模式,而不是想杂耍那样得到迭代序列中的元素。

值得注意的是,*语法对未知长度的元组序列尤其有用。假如有一个标记过的元组序列:

<span>records</span> <span>=</span> <span>[</span>
     <span>(</span><span>'foo'</span><span>,</span> <span>1</span><span>,</span> <span>2</span><span>),</span>
     <span>(</span><span>'bar'</span><span>,</span> <span>'hello'</span><span>),</span>
     <span>(</span><span>'foo'</span><span>,</span> <span>3</span><span>,</span> <span>4</span><span>),</span>
<span>]</span>

<span>def</span> <span>do_foo</span><span>(</span><span>x</span><span>,</span> <span>y</span><span>):</span>
    <span>print</span><span>(</span><span>'foo'</span><span>,</span> <span>x</span><span>,</span> <span>y</span><span>)</span>

<span>def</span> <span>do_bar</span><span>(</span><span>s</span><span>):</span>
    <span>print</span><span>(</span><span>'bar'</span><span>,</span> <span>s</span><span>)</span>

<span>for</span> <span>tag</span><span>,</span> <span>*</span><span>args</span> <span>in</span> <span>records</span><span>:</span>
    <span>if</span> <span>tag</span> <span>==</span> <span>'foo'</span><span>:</span>
        <span>do_foo</span><span>(</span><span>*</span><span>args</span><span>)</span>
    <span>elif</span> <span>tag</span> <span>==</span> <span>'bar'</span><span>:</span>
        <span>do_bar</span><span>(</span><span>*</span><span>args</span><span>)</span>
Copy after login

*解压在和处理特定字符串结合使用时也很有用,比如:

<span>>>></span> <span>line</span> <span>=</span> <span>'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'</span>
<span>>>></span> <span>uname</span><span>,</span> <span>*</span><span>fields</span><span>,</span> <span>homedir</span><span>,</span> <span>sh</span> <span>=</span> <span>line</span><span>.</span><span>split</span><span>(</span><span>':'</span><span>)</span>
<span>>>></span> <span>uname</span>
<span>'nobody'</span>
<span>>>></span> <span>homedir</span>
<span>'/var/empty'</span>
<span>>>></span> <span>sh</span>
<span>'/usr/bin/false'</span>
<span>>>></span>
Copy after login

有时你可能会想解压一些值然后抛弃掉。你不能在解压时只指定一个*,你可以使用普通的要丢弃掉的变量名,比如_或者ign(ignore)。举例:

<span>>>></span> <span>record</span> <span>=</span> <span>(</span><span>'ACME'</span><span>,</span> <span>50</span><span>,</span> <span>123.45</span><span>,</span> <span>(</span><span>12</span><span>,</span> <span>18</span><span>,</span> <span>2012</span><span>))</span>
<span>>>></span> <span>name</span><span>,</span> <span>*</span><span>_</span><span>,</span> <span>(</span><span>*</span><span>_</span><span>,</span> <span>year</span><span>)</span> <span>=</span> <span>record</span>
<span>>>></span> <span>name</span>
<span>'ACME'</span>
<span>>>></span> <span>year</span>
<span>2012</span>
<span>>>></span>
Copy after login

*解压和列表处理在不同的功能语言上有一定相似性。例如,你有一个列表,你可以很容易的将其分解为头尾部件:

<span>>></span> <span>items</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>10</span><span>,</span> <span>7</span><span>,</span> <span>4</span><span>,</span> <span>5</span><span>,</span> <span>9</span><span>]</span>
<span>>>></span> <span>head</span><span>,</span> <span>*</span><span>tail</span> <span>=</span> <span>items</span>
<span>>>></span> <span>head</span>
<span>1</span>
<span>>>></span> <span>tail</span>
<span>[</span><span>10</span><span>,</span> <span>7</span><span>,</span> <span>4</span><span>,</span> <span>5</span><span>,</span> <span>9</span><span>]</span>
<span>>>></span>
Copy after login

有人可能会想写这么一个函数,为了完成某种聪明的递归算法而执行这样的分割:

<span>>>></span> <span>def</span> <span>sum</span><span>(</span><span>items</span><span>):</span>
<span>...</span>     <span>head</span><span>,</span> <span>*</span><span>tail</span> <span>=</span> <span>items</span>
<span>...</span>     <span>return</span> <span>head</span> <span>+</span> <span>sum</span><span>(</span><span>tail</span><span>)</span> <span>if</span> <span>tail</span> <span>else</span> <span>head</span>
<span>...</span>
<span>>>></span> <span>sum</span><span>(</span><span>items</span><span>)</span>
<span>36</span>
<span>>>></span>
Copy after login

然而,要注意的是,因为固有的限制,递归真的不是Python的强项。因此上述代码在实现中只能算是有学术价值。

Related labels:
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template