Python tricks(2) -- method默認參數和閉包closure

Python的method能夠設置默認參數, 默認參數若是是可變的類型, 好比list, map等, 將會影響全部的該方法調用. html

下面是一個簡單的例子python

def f(a=None, l=[]):
    if not a:
        return l
    l.append(a)
    return l

if __name__ == "__main__":
    print f("a")
    print f("b")
    print f("b")
    print f(l=[])
    print f()

輸出結果以下:閉包

['a']
['a', 'b']
['a', 'b', 'b']
[]
['a', 'b', 'b']

咱們能夠看到f的默認參數l在全部的方法調用中都受到影響了, 這個可能並不必定符合默認參數設置的初衷. app

想要避免這種影響, 能夠這樣作.htm

def f(a=None, l=None):
    if not l:
        l = []
    if not a:
        return l
    l.append(a)
    return l

if __name__ == "__main__":
    print f("a")
    print f("b")
    print f("b")
    print f(l=[])
    print f()

將l設置爲None, 在方法內部判斷, 並初始化爲空, 這樣改變後的輸出爲:對象

['a']
['b']
['b']
[]
[]

具體能夠查閱官方文檔的說明[參考1].blog

下面再來講說閉包.生命週期

我我的理解, 閉包的形式是方法的嵌套, 主要的做用是爲了在整個調用過程當中保存方法的某些狀態. 有些時候method的默認參數也能夠作到保存方法狀態.文檔

用dict保存一些變量信息, 相似context的東西.get

閉包實現:

def context():
    data = {}

    def _context(key, value=None):
        if value:
            data[key] = value
            return data
        else:
            return data.get(key, None), data

    return _context

c = context()
print c("key")
print c("key", "value")
print c("key")

方法默認參數的實現

def d(key, value=None, data={}):
    if value:
        data[key] = value
        return data
    else:
        return data.get(key, None), data

print d("key")
print d("key", "value")
print d("key")

經過實現類的magic method來實現

class e(object):
    def __init__(self):
        self.data = {}

    def __call__(self, key, value=None):
        if value:
            self.data[key] = value
            return self.data
        else:
            return self.data.get(key, None), self.data

f = e()
print f("key")
print f("key", "value")
print f("key")

三種實現的輸出結果都是同樣的

(None, {})
{'key': 'value'}
('value', {'key': 'value'})

在python中方法自己也是一個對象, 能夠有本身的屬性等, 經過第三種實現, 咱們能夠理解默認參數是方法對象的一個屬性, 伴隨其生命週期.

使用def func()定義的時候就是定義了一個方法的類, 以後獲取了一個名爲func的實例化對象.

 

可能有人會奇怪, 這種東西哪裏有使用的場景了? 我能想到的一個場景就是, 我想經過查找字典的方式獲取一個信息, 這個字典是一個大文件(加載耗時), 我只但願加載一次, 這個時候閉包能夠發揮其特殊的做用, 並且代碼也比較優雅.

 

本文是筆者對於python方法的一些理解. 水平有限, 歡迎拍磚!

 

參考文檔:

  1. Python Docs: http://docs.python.org/2/tutorial/controlflow.html#default-argument-values
相關文章
相關標籤/搜索