1. 程式人生 > >python函式引數的填坑之路

python函式引數的填坑之路

背景

最近在看廖雪峰老師的python3教程之函式的引數
受益匪淺,但是在實踐的過程中,發現了一些不解之謎

兩個錯誤

import _thread
import time
def func1(x):
	while x:
		print(x)
		x = x -1
_thread.start_new_thread(function=func1,args=(5,),kwargs=None)
time.sleep(6)

再看python3中start_new_thread()函式的宣告

def start_new_thread(function, args, kwargs=None):

按照我們的理論,我們開啟多執行緒的那句程式碼是完全沒有問題的,可是事實上它報錯:

TypeError: start_new_thread() takes no keyword arguments

難道我們的理論有問題?帶著這個疑問,我又遇到一個問題:

import threading
def func1(x):
	while x:
		print(x)
		x = x -1
threading.Thread(func1,(5,)).start()

再看python3中Thread類構造()函式的宣告

def __init__(self, group=None, target=None, name=None,
             args=(), kwargs=None, *, daemon=None):

它居然又報錯?

AssertionError: group argument must be None for now

探討過程

(以下過程針對第二個錯誤,第一個錯誤道理類似)
帶著疑問,我看了Thread類的建構函式

	    def __init__(self, group=None, target=None, name=None,
             args=(), kwargs=None, *, daemon=None):
              """This constructor should always be called with keyword arguments. Arguments are:
              
               *group* should be None; reserved for future extension when a ThreadGroup
                class is implemented.
                
                *target* is the callable object to be invoked by the run()
                method. Defaults to None, meaning nothing is called.
                。。。略
                
                assert group is None, "group argument must be None for now"
                。。。略

我們看到,第三行說明,本函式只接受關鍵字實參呼叫,所以我們之前的程式碼改成

import threading
def func1(x):
	while x:
		print(x)
		x = x -1
threading.Thread(target=func1,args=(5,)).start()

就能順利開啟子執行緒了,那麼它是如何實現只能接受關鍵字引數的呢?
我們看到Thread類的建構函式定義中有一句這樣的斷言

assert group is None, "group argument must be None for now"

意思是,如果引數group為空,通過;如果非空,報錯,並給出reasongroup argument must be None for now,如果我們按照之前的位置引數呼叫的話,由於group是第一個引數,一下在就被賦值,非空,丟擲異常,這符合我們之前的實踐。同時,我在網上搜集了許多資料,諸如修飾器之類的也能使函式只接受關鍵字引數 。

錯誤一探討過程道理類似,在此不再贅述。

驗證及結論

編碼

class MyThread:

	def __init__(self, group=None, target=None, name=None,
	args=(), kwargs=None, *, daemon=None):
		print('Thread sucess')
	
	def start_new_thread(function, args, kwargs=None):
	print('_thread sucess')
	
MyThread()
MyThread.start_new_thread(args=2,kwargs=3,function=1)

輸出如下:

Thread sucess
_thread sucess

顯而易見,我們之前所學的理論是正確的,只不過在具體的編碼中,我們通過編碼修改
理論,使之看上去似乎和之前的理論相矛盾,千萬不要被矇蔽了。