當前位置: 妍妍網 > 辦公

10多萬人關註的幾個Python問題

2024-04-15辦公

本文挑選了 StackOverflow 上被點贊最多的10個問題,其中總點贊數超過了5萬,考慮到很多人只看不點贊,預估至少有10萬人對這些問題感興趣!

這麽多人點贊,說明兩個問題:

  1. 這些問題很常用,編程的時候經常碰到

  2. 這些問題不簡單,否則不用去網上問

10個問題,看看你會幾個?

  1. yield 關鍵詞是做什麽的?

  2. if name == ' main ' 是做什麽的 ?

  3. Python 有三元運算子嗎?

  4. Python 的 meta classes 是做什麽的?

  5. 如果在不出異常的情況下檢查檔是否存在?

  6. 如何一句話合並兩個字典?

  7. Python 如何呼叫外部命令,比如啟動QQ?

  8. 如何安全的建立一個多層資料夾?

  9. 迴圈中如何存取下標?

  10. staticmethod 和 classmethod 的區別?

這10個問題,有的復雜,有的簡單。你會幾個呢?可以在評論區留言。

我原本打算講解10個問題,但由於篇幅原因,本文只涵蓋了被問最多的一個問題,後續文章可能會涵蓋多個問題。

下面我們重點看第一個問題:

yield關鍵詞是做什麽的?

這個問題是所有Python問題的排名第一:

  1. 有10000多人對問題點贊,表示有同樣疑問。

  2. 其中高贊回答有15000多點贊。

  3. 有超過2百40萬的瀏覽。

問題詳細內容?

Yield關鍵詞是做什麽的?

比如下面的程式碼:

def_get_child_candidates(self, distance, min_dist, max_dist):
if self._leftchild and distance - max_dist < self._median:
yield self._leftchild
if self._rightchild and distance + max_dist >= self._median:
yield self._rightchild

這是呼叫的程式碼:

result, candidates = [], [self]
while candidates:
node = candidates.pop()
distance = node._get_dist(obj)
if distance <= max_dist and distance >= min_dist:
result.extend(node._values)
candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

當_get_child_candidates被呼叫時,發生了什麽?返回了一個list嗎?還是一個元素?它會被反復調嗎?後續呼叫什麽時候停止?

看著有點懵?可以繼續往下看解答,然後再回來看問題。

最高贊回答 (15000多贊)

要理解yield,先理解generators,要理解generators先理解iterable(可叠代的)。

iterables

當你建立1個list,你可以一個個讀取它的值,這叫做叠代:

>>> mylist = [123]
>>> for i in mylist:
...  print(i)
1
2
3

上面mylist是一個iterable(可以被叠代的)。當你使用一個列表推導式,你建立了一個列表,也就是一個iterable:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...  print(i)
0
1
4

所以可以使用for...in...語法遍歷的就是iterable:list, str, file等等

這些iterable很有用,你可以迴圈存取他們。但是它們所有的值都保存在記憶體中。如果你的list中有10億個字串的時候,建立這個list會很慢,而且會很占用記憶體,所以我們需要genertor.

generators

generator是iterable,可以被迴圈。但和上面不一樣,它一般只能被迴圈一次。它不會把所有的值保存在記憶體中,他們在迴圈中動態產生元素的值。

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...  print(i)
0
1
4

這個生成器和列表推導式幾乎一樣,唯一區別使用小括弧(),而不是中括弧[]. 但,你不能兩次使用for i in mygenerator,因為生成器只能被迴圈一次:他們計算0x 0,返回結果,自己並不保存,下一次呼叫它,他計算1x 1,以此類推。

yield

yields是一個關鍵詞,可以先理解成和return一樣,區別是它返回一個generator.

>>> defcreateGenerator():
...  mylist = range(3)
... for i in mylist:
... yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
<generator object createGenerator at 0xb7555c34>
>>> for i in mygenerator:
...  print(i)
0
1
4

上面這個例子先建立了range,已經占用了記憶體,但平方數沒有占用。這個例子不是很好,這是原作者舉的,我的視訊中應該有更好的例子。

首先,因為yield的存在,當你呼叫上面的函式,裏面的程式碼並沒有執行,而不是返回了一個generator。

然後是關鍵的地方:

  • 當for迴圈第一次呼叫generator的時候,它會從頭開始執行,直到yield關鍵詞,返回第一個值,也就是0。

  • 然後記住執行到哪一行程式碼,也就是yield的位置。

  • 下次for迴圈再次呼叫它,它從yield的下一行繼續執行,直到再次碰到yield,返回下一個值,也就是1.

  • 這個過程一直重復,直到generator中沒有內容了。例子中就是range裏的數位被用完。

  • 現在再看看最開始的問題:

    這是一個對樹的遍歷演算法,尋找樹上符合條件的節點。程式碼中加了詳細的中文註釋。

    generator:

    # 這個函式會返回一個生成器(Generator),這是一個二元樹的node物件中的方法
    def_get_child_candidates(self, distance, min_dist, max_dist):
    # 如果還有左孩子,並且距離符合條件,返回左孩子,然後暫停在這裏
    if self._leftchild and distance - max_dist < self._median:
    yield self._leftchild
    # 如果還有右孩子,並且距離符合條件,返回右孩子,然後暫停在這裏
    if self._rightchild and distance + max_dist >= self._median:
    yield self._rightchild
    # 如果執行到了這裏,說明沒有符合條件的左右孩子了,生成器空了,就叠代結束了。

    caller:

    # 建立一個空的列表,和當前物件節點
    result, candidates = list(), [self]
    # 迴圈,開始裏面只有自己
    while candidates:
    # 彈出最後一個節點
    node = candidates.pop()
    # 獲得obj物件和目標節點的距離
    distance = node._get_dist(obj)
    # 如果距離ok,寫入到結果列表中
    if distance <= max_dist and distance >= min_dist:
    result.extend(node._values)
    # 把自己的子節點加入到candidates中,這樣迴圈會繼續,直到樹上的所有節點都被遍歷
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
    return result






    作者: 麥叔

    來源 :麥叔編程

    Crossin的新書【 碼上行動:用ChatGPT學會Python編程 】已經上市了。 本書以ChatGPT為輔助,系統全面地講解了如何掌握Python編程,適合Python零基礎入門的讀者學習。

    購買後可加入讀者交流群,Crossin為你開啟陪讀模式,解答你在閱讀本書時的一切疑問。

    Crossin的其他書籍:

    添加微信 crossin123 ,加入編程教室共同學習 ~

    感謝 轉發 點贊 的各位~