用python的內建函數print時,大家會發現它是支援任意多個參數,也就是說,print的調用參數是不固定的。例如:
print "你好"
print "我是",name
print "現在是", time , " 你在幹什麼呢", name , "!"
這得益與python的“可變參數”,在Python裡,可以使用*和**來設定可變參數,它們的區別是*傳遞一個參數元組,**傳遞一個參數字典,二者可以同時混合使用。混合使用時要加些小心,因為python中他們的次序是重要的。參數歸為4類,不是所有的類別都需要。他們必須按下面的次序定義,不用的可以跳過。
1)必須的參數
2)可選的參數
3)過量的位置參數
4)過量的關鍵字參數
def funName(a, b=None, *c, **d):
這個次序是必須的,因為*args和**kwargs只接受那些沒有放進來的其他任何參數。沒有這個次序,當你調用一個帶有位置參數的函數,python就不知道哪個值是已聲明參數想要的,也不知道哪個被作為過量參數對待。
也要注意的是,當函數能接受許多必須的參數和可選的參數,那它只要定義一個過量的參數類型即可。看下面的例子:
| 代碼如下 |
複製代碼 |
def add(a, b, c): return a + b + c >>> add(1, 2, 3) 6 >>> add(a=4, b=5, c=6) 15 >>> args = (2, 3) >>> add(1, *args) 6 >>> kwargs={'b': 8, 'c': 9} >>> add(a=7, **kwargs) 24 >>> add(a=7, *args) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: add() got multiple values for keyword argument 'a' >>> add(1, 2, a=7) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: add() got multiple values for keyword argument 'a' |
注意這個例子的最後幾行,特別留意當傳遞一個元組作為可變參數時,是否要顯式的傳遞關鍵字參數。因為python使用次序規則來擴充過量的參數,那位置參數要放在前面。這個例子中,最後兩個調用是相同的,python不能決定那個值是給a的。
下面舉一個例子來模仿print的實現:
| 代碼如下 |
複製代碼 |
>>> import sys >>> def myprint(*argv): sys.stdout.write(" ".join([str(i) for i in argv]) + "n") >>> print "I believe", 2012, "is the end of the world." I believe 2012 is the end of the world. >>> myprint("I believe", 2012, "is the end of the world.") I believe 2012 is the end of the world. >>> print "tuple:", (1, 2, 3), "list:", [1, 2, 3], "dict:", {"begin":-2012, "end":2012} tuple: (1, 2, 3) list: [1, 2, 3] dict: {'begin': -2012, 'end': 2012} >>> myprint("tuple:", (1, 2, 3), "list:", [1, 2, 3], "dict:", {"begin":-2012, "end":2012}) tuple: (1, 2, 3) list: [1, 2, 3] dict: {'begin': -2012, 'end': 2012} |
print預設是輸出到stdout中,在終端啟動並執行程式,無重新導向的情況下,print輸出到控制台。如果要做代碼裡實現把print的輸出寫入到log檔案中,可以通過修改stdout的檔案對象來實現。同理,重定位標準輸入和標準錯誤輸出分別修改stdin和stderr的檔案對象即可。
下面的例子捕捉所有print的輸出,讓輸出的每一行前增加一個時間的顯示:
| 代碼如下 |
複製代碼 |
import sys, time class MyOutput(): def __init__(self, fd): self.formatTime() self.out = fd self.newLine = True def formatTime(self): return time.strftime("%H:%M:%S ", time.localtime()) def write(self, s): if self.newLine: self.out.write(self.formatTime()) self.newLine = False self.out.write(s) if s.endswith("n"): self.newLine = True def flush(self): self.out.flush() sys.stdout = MyOutput(sys.stdout) print "Program begin." mylist = [5, 4, 3, 2, 1] print "prev: ", mylist mylist.sort() print "after: ", mylist time.sleep(3) print "Program end." |