問題:
你需要從一個可迭代對象中拆解出N個元素,但是它可能多於N個元素並導致拋出“too many values to unpack”的異常
解決:
python的“帶星參數”可以搞定這個問題。比如說,你開了一門課並且決定在期末的時候,你將去掉第一次和最後一次的家庭作業的成績再計算出剩餘的平均成績。如果只有四次作業,那就是小意思妥妥的無壓力秒殺。可如果是有24次作業呢? 帶星參數將能很好地解決這個問題:
def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)
另一個栗子,假設你有包含了用戶名,郵箱及一坨長度任意的電話號碼。你可以這麼處理:
P.S python2.7.6會報錯
書上的例子有一處打印錯
>>> name, email, *phone_numbers = record >>> record = ('Dave', '[email protected]', '773-555-1212', '847-555-1212') >>> name, email, *phone_numbers = record #書上此處爲 user_record >>> name 'Dave' >>> email '[email protected]' >>> phone_numbers ['773-555-1212', '847-555-1212'] >>>
無論有多少個要拆解或爲None phones_number變量總會是一個列表,因此在對phones_number變量做處理時,無須做是否爲列表的類型檢查。(撒花!!)
帶星參數 也可用於列表開頭。比如說,你有一個關於你公司過去8個季度的銷售數據序列。如果你想知道最後一個季度與前七個季度的平均值相比哪個更好。你可以這麼處理:
*trailing_qtrs, current_qtr = sales_record
trailing_avg = sum(trailing_qtrs) / len(trailing_qtrs)
return avg_comparison(trailing_avg, current_qtr)
栗子!栗子:
>>> *trailing, current = [10, 8, 7, 1, 9, 5, 10, 3] >>> trailing [10, 8, 7, 1, 9, 5, 10] >>> current 3 >>>
討論:
可擴展的迭代對象的拆解適用於拆解長度未知或任意的可迭代對象。經常的情況是這類可迭代對象的一些結構是已知的。帶星參數可以方便讓你訪問到相關的元素。
>>> records = [ ('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4)] >>> def do_foo(x, y): print('foo', x, y) >>> def do_bar(s): print('bar', s) >>> for tag, *args in records: if tag == 'foo': do_foo(*args) elif tag == 'bar': do_bar(*args) foo 1 2 bar hello foo 3 4 >>>
帶星的拆解 在諸如抄截字符串時也很有用。
>>> line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false' >>> uname, *fields, homedir, sh = line.split(':') >>> uname 'nobody' >>> homedir '/var/empty' >>> sh '/usr/bin/false' >>>
有時,我會想幹掉分離出來的元素。你不能就單單使用帶星參數了,你可以使用一個常見的表示可拋棄的變量名 像是 ‘_’或者 ign(ignored)
>>> record = ('ACME', 50, 123.45, (12, 18, 2012)) >>> name, *_, (*_, year) = record >>> name 'ACME' >>> year 2012 >>>
列表:
>>> items = [1, 10, 7, 4, 5, 9] >>> head, *tail = items >>> head 1 >>> tail [10, 7, 4, 5, 9] >>>
有人會想到寫個方法以便執行一些遞歸算法
>>> def sum(items): head, *tail = items return head + sum(tail) if tail else head >>> sum(items) 36 >>>