Python:列表也能拆包?

丹楓無跡發表於2019-05-15

前幾天,微信學習群裡有個小夥伴在看書時遇到了這樣一個問題,在群裡提問,看下圖:

這是常用的 matplotlib 庫,只是一般我們呼叫 plot 方法繪圖時,不會去關心它的返回值。然而 plt1, = plt.plot(...) 這種寫法是什麼意思?被賦值的變數和賦值符號之間多了個逗號。

我的確從來沒關心過 plot 函式的返回值是什麼,所以當我看到這個截圖的時候,第一反應是以為返回值有多個,程式碼只取了第一個,剩餘的被忽略了。這種情況一般都是用 _ 做佔位符,來忽略不關心的值。

佔位符 _ 也可以省略嗎?我迅速開啟 PyCharm 驗證了一把,事實證明,_ 不可以省略,我的想法是錯了。

為了查明原因,我去查了 matplotlib 的原始碼,發現 plot 函式返回的是一個列表,原始碼如下:

def plot(self, *args, **kwargs):
    scalex = kwargs.pop('scalex'True)
    scaley = kwargs.pop('scaley'True)

    if not self._hold:
        self.cla()
    lines = []

    kwargs = cbook.normalize_kwargs(kwargs, _alias_map)

    for line in self._get_lines(*args, **kwargs):
        self.add_line(line)
        lines.append(line)

    self.autoscale_view(scalex=scalex, scaley=scaley)
    return lines

我這才反應過來,這是列表拆包啊。變數後面的逗號,是因為返回的列表中只有一個元素,所以拆包的時候變數後面要加個逗號,標明這是拆包,不是賦值。

程式碼中,我們用的比較多的是元組拆包,各種書裡也多是講元組拆包,所以忽略了列表也是可以拆包的。看下面的例子:

x, y = [12]
print(x, y)

輸出:

1 2

不僅是元組和列表,所有可迭代物件都可以拆包。我們可以自定義一個可迭代物件(只需要實現其協議即 __iter__ 方法即可),來驗證一下,程式碼如下:

class TestClass:
    def __init__(self):
        self._list = range(3)

    def __iter__(self):
        for i in self._list:
            yield i


x, y, z = TestClass()
print(x, y, z)

輸出:

0 1 2

相關文章