幾個易錯的python小知識點

2023-10-09 21:02:23

大家好,我是暴走の海鴿~

本期整理了幾個基礎python防坑小常識,希望對大家有所幫助。

1. type == object?

執行以下程式碼的結果是什麼:

>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>> isinstance(object, object)
True
>>> isinstance(type, type)
True
  • isinstance(type, object):這個表示式返回 True,因為在 Python 中,type 是一種型別,而 object 也是一種型別,它們都是物件的基礎類別。

  • isinstance(object, type):同樣返回 True,因為 object 是 Python 中所有物件的基礎類別,因此它也可以被視為一種型別。

  • isinstance(object, object):這個表示式也返回 True,因為 object 是 object 型別的範例,它自己也是一種物件。

  • isinstance(type, type):同樣返回 True,因為 type 本身也是一種型別,可以用來描述其他型別。

在 Python 中,所有東西都是物件,因此對於物件的任何範例檢查都將返回True

  • isinstance(Anything, object) --> True

Python 的 type 表示構建所有 Python 型別的元類。因此,所有型別,如 int、str、object 都是 type 類的範例,而 type 類本身也是一個物件,與 Python 中的一切物件一樣。

type 是 Python 中唯一一個自身是自己範例的物件。

2. all函數、any函數

執行以下程式碼的結果是什麼:

>>> all([True, True, True])
True
>>> all([True, True, False])
False
>>>
>>>
>>> all([True, True, {}])
False
>>> any([True, True, {}])
True
>>>
>>> all([])
True
>>>
>>> any([])
False

根據內建函數any的定義,我們知道它將:

如果 iterable 中的任何元素為 true,則返回 true。

Python 中的邏輯運運算元是惰性的,演演算法是查詢第一個 true 元素的出現情況,如果沒有找到,則返回 False。由於序列為空,因此沒有元素可以是 true,因此 any([]) 返回 False。

all的例子稍微有些複雜,因為它表示真空的真實性。與鏈式惰性邏輯運運算元類似,演演算法是查詢第一個 false 元素,如果沒有找到,則返回 True。由於在空序列中沒有false 元素,因此 all([]) 返回 True。

>>> def my_all(iterable):
...     for element in iterable:
...         if not element:
...             return False
...     return True
...
>>> my_all([])
True
>>> my_all([True, True, {}])
False

3. 鏈式運算

執行以下程式碼的結果是什麼:

>>> False == (False in [False])  # 這個好理解!
False
>>> (False == False) in [False]  # 這個也好理解!!
False
>>> True in [False]
False

>>> False == False in [False]  # 那這個是為什麼呢?
True

在python中,==運運算元和in運運算元都具有相同的優先順序,並且它們都是從左到右結合的。因此False == False in [False]實際上是(False == False) and (False in [False]的簡寫形式。

加個栗子理解下:

>>> '1' in '11' == True
False

>>> 4 > 3 == 3
True

'1' in '11' == True

python運運算元優先順序和結合性

4. sorted函數和reversed函數

執行以下程式碼的結果是什麼:

>>> x = 1, 2, 3
>>>
>>> sorted(x) == x
False
>>>
>>> sorted(x)
[1, 2, 3]
>>> x
(1, 2, 3)
>>>
>>> y = reversed(x)
>>> sorted(y) == sorted(y)
False
>>>
>>>
>>> y
<reversed object at 0x7fb3aa5370>

注意:sorted 方法返回的是一個list,reversed 方法返回的是一個iterator。

5. 布林值

執行以下程式碼的結果是什麼:

>>> 1 == True
True
>>> False ** False == True
True
>>> 0 == False
True

Python 將 False 視為 0, True 視為 1

6. round函數

執行以下程式碼的結果是什麼:

>>> round(1 / 2)
0
>>>
>>>
>>> round(3 / 2)
2
>>>
>>> round(5 / 2)
2

為什麼 round(5 / 2) 返回 2 而不是 3?這裡的問題在於 Python 的 round 方法實現了銀行家舍入,其中所有半值都將四捨五入到最接近的偶數
即:

  • 如果小數部分小於 0.5,則捨棄小數部分,不進行舍入。

  • 如果小數部分大於 0.5,則向上舍入到最接近的整數。

  • 如果小數部分等於 0.5,且前一位的整數部分是奇數,則向上舍入到最接近的偶數。

  • 如果小數部分等於 0.5,且前一位的整數部分是偶數,則向下舍入到最接近的偶數。

7. python列表+和+=的區別

+

>>> a = [1, 2, 3]
>>> b = a
>>>
>>>
>>> a = a + [4]
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3]

+=

>>> list1 = [1, 2, 3]
>>> list2 = list1
>>> list1 += list2
>>>
>>> list1
[1, 2, 3, 1, 2, 3]
>>> list2
[1, 2, 3, 1, 2, 3]
  • +用於連線兩個列表,生成一個新的列表。
  • +=用於將一個列表與另一個列表相加,並將結果儲存在原始列表中,修改原始列表。

8. 列表del元素

執行以下程式碼的結果是什麼:

>>> my_list = [1, 2, 3, 4, 5]
>>> for i in range(len(my_list)):
...     if my_list[i] % 2 == 0:
...         del my_list[i]
...

執行結果:

>>> my_list = [1, 2, 3, 4, 5]
>>> for i in range(len(my_list)):
...     if my_list[i] % 2 == 0:
...         del my_list[i]
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
IndexError: list index out of range

在這個範例中,我們試圖刪除列表中的偶數元素。然而,這個程式碼會導致錯誤,因為在刪除元素後,列表的長度發生變化,但迴圈中的索引 i 仍然會增加,這可能會導致索引超出列表邊界的錯誤。

為了避免這種錯誤,可以使用以下方法之一來移除元素:

  1. 建立一個新列表,只包含要保留的元素,而不刪除原始列表的元素。
my_list = [1, 2, 3, 4, 5]
new_list = [x for x in my_list if x % 2 != 0]
  1. 使用倒序迴圈,以避免索引問題。
my_list = [1, 2, 3, 4, 5]
for i in range(len(my_list) - 1, -1, -1):
    if my_list[i] % 2 == 0:
        del my_list[i]

這些方法可以避免在移除元素時引發錯誤,並確保程式碼正常執行。

9. 修改sum([])的預設返回值

我們知道sum([])的返回值為0,那有沒有辦法修改呢,比如返回0.0,答案是:有的。而且就在sum函數的簽名裡。

>>> sum("", [1])
[1]
>>> sum("", [1, 2])
[1, 2]
>>>
>>>
>>> sum([1, 2])
3
>>>
>>> sum([1, 2, 3], 1)
7
>>>
>>> sum([1, 2, 3], 9)
15

>>> sum([], {1, 2, 3})
{1, 2, 3}

>>> help(sum)
Help on built-in function sum in module builtins:

sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers

    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.

小結

儘管如此,Python 仍然以其清晰透明的程式語言特性而聞名。在編寫本文時,我遇到了許多這樣的程式碼片段,它們可能在早期版本的 Python 中表現出反直覺的行為,但在新版本中得到了修復或社群的解釋。上述範例代表了 Python 語法的某些邊界情況,而在實際的商業專案中,遇到這些情況的機會相對較小。

然而,檢查和理解這樣的「陷阱」可以幫助您更深入地理解 Python 語言的內部結構,從而避免在編寫程式碼時使用不常見的用例和可疑的程式設計做法,這可能會導致意外的錯誤和故障。因此,瞭解 Python 的行為和語法規則仍然是一個有價值的努力,尤其是對於那些希望編寫高質量、可維護程式碼的開發人員來說。

❝ 喜歡這篇文章的話,就點個關注吧,或者關注一下我的公眾號『海哥python』也可以,會持續分享高質量Python文章,以及其它內容。❞