在網絡上各種selenium自動化測試框架搭建的過程中,對於selenium顯示等待有好幾種寫法,包含但不限於以下幾種:
-
寫法1:
+++ from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait self.driver = webdriver.Chrome() WebDriverWait(self.driver).until(lambda x:x.find_element(*loc)) +++
-
寫法2:
+++ from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait self.driver = webdriver.Chrome() WebDriverWait(self.driver).until(EC.presence_of_element_located(loc)) +++
-
寫法3:
+++ from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC self.driver = webdriver.Chrome() EC.presence_of_element_located(loc)(self.driver) +++
新手看着可能有些暈乎乎的,我曾經也是看着也挺暈的。接下來我就要來說說這幾種寫法是怎么運行的。
寫法1
先來簡單看看寫法,在WebDriverWait初始化時傳入了driver參數,然后調用until方法,傳入了一個lambda匿名函數
WebDriverWait(self.driver).until(lambda x:x.find_element(loc))
為了看清運行原委我們得去看看源碼(如果你創建了虛擬環境的話,路徑會如下所示):
venv\Lib\site-packages\selenium\webdriver\support\wait.py

可以看到driver參數傳進來之后被賦值給了WebDriverWait類變量_driver,那么他在哪里使用了呢,我們接着往下看:

在WebDriverWait類的until函數中使用了。
先看一下until的函數注釋(翻譯):調用驅動程序提供的方法作為參數,直到返回值不是False。
結合上文,我們傳入的method是lambda x:x.find_element(*loc)
是一個匿名函數。

結合官方文檔的說明,f(0)可以實現給lambda傳入參數。lambda可以引用所在域的變量,x引用的域變量就是WebDriverWait的self._driver類變量 ,lambda x:x.find_element(loc)
表達式就被替換成為了self.driver.find_element就可以正常的使用driver使用一樣
寫法1的運行大致就是這樣了。
寫法2
寫法2我們必須關聯以下expected_conditions模塊才能看清楚
venv\Lib\site-packages\selenium\webdriver\support\expected_conditions.py

可以看到EC中的都是類,函數只有兩個,后面介紹
第二種寫法里面我們先看until里面的部分,locator的參數就是我們傳入的loc,loc是什么呢,就是(By.ID,'#su')
這種。
然后下面實現了一個__call__
方法,里面傳入的參數就是driver,這個方法是什么意思呢,請看下面的小提示。
小提示:重載運算符(魔法方法),python中的可調用對象包括
自定義的函數
、python內置函數
,類的實例化對象
,method() =method.__call__()
函數。
這個方法還是通過method(self._driver)方式傳入了driver的實例對象。
然后第64行把這兩個參數傳給了_find_element方法,EC模塊中的兩個函數這個就是其中之一:

這個函數返回了什么呢,第411行,返回了driver.find_element()方法,通過__call__
方法返回了self.driver.find_element。
由此我們可以推斷出寫法1和寫法2是完全一樣的,包括解包的時機。
寫法3
讀完了寫法1和寫法2,寫法3會顯得更簡單
presence_of_element_located(傳入的參數)(傳入的driver),在前面小提示已經說過,第二個括號中的正是通過__call__
方法來實現的重載運算()調用。
然后兩個參數傳入進去后,presence_of_element_located函數返回driver.find_element。
和寫法1和寫法2不同的是外層沒有包含顯示等待的類。所以寫法3不支持顯示等待,只是返回了一個普通的driver方法或基於driver方法實現的結果。