首頁 > 資料庫 > mysql教程 > 1.2.从任意长度的迭代中解压元素

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

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
發布: 2016-06-07 15:32:56
原創
954 人瀏覽過

问题 想从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>
登入後複製

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

<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>
登入後複製

值得注意的是,变量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>
登入後複製

在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>
登入後複製

讨论

扩展的迭代解包是专为位置或任意长度的迭代序列解包的,通常情况下,这些迭代序列在结构上有已知的组件或者模式(比如数字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>
登入後複製

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

<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>
登入後複製

有时你可能会想解压一些值然后抛弃掉。你不能在解压时只指定一个*,你可以使用普通的要丢弃掉的变量名,比如_或者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>
登入後複製

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

<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>
登入後複製

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

<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>
登入後複製

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

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板