來挑戰下這十個 Python 問題,你會嗎?

WBOY
發布: 2023-05-02 11:16:06
轉載
1035 人瀏覽過

你好,我是徵哥,Python 很容易入門,但卻不易精通,即使有經驗的工程師,某些現像也是反直覺的,以下這10 個問題就非常有趣,且有一定的挑戰性,結果可能會讓你感到困惑,來看看你能回答正確幾個?

這裡先給出題目,最後給出答案,建議先拿個紙,寫下你的答案,最後再驗證。

請寫出以下程式碼的輸出結果:

1.懶惰的Python

class A:
def function(self):
return A()
a = A()
A = int
print(a.function())
登入後複製
登入後複製

2.四捨五入

>>> round(7 / 2)
>>> round(3 / 2)
>>> round(5 / 2)
登入後複製

3.type 和object

>>> isinstance(type, object)
>>> isinstance(object, type)
>>> isinstance(object, object)
>>> isinstance(type, type)
登入後複製

4、空的布林值

>>> any([])
>>> all([])
登入後複製

5.類別內部函數的優先權

class A:
answer = 42
def __init__(self):
self.answer = 21
self.__add__ = lambda x, y: x.answer + y
def __add__(self, y):
return self.answer - y
print(A() + 5)
登入後複製
登入後複製

6.求和

>>> sum("")
>>> sum("", [])
>>> sum("", {})
登入後複製

7.意外的屬性

>>> sum([
el.imag 
for el in [
0, 5, 10e9, float('inf'), float('nan')
]
])
登入後複製

8.輸出負數倍的字串

>>> "this is a very long string" * (-1)
登入後複製

9.見過負數的0

max(-0.0, 0.0)
登入後複製
登入後複製

10.違反數學規則

>>> x = (1 << 53) + 1
>>> x + 1.0 > x
登入後複製

答案與解釋

以下結果皆在Python 3.8.5 版本驗證。

1.懶惰的Python

class A:
def function(self):
return A()
a = A()
A = int
print(a.function())
登入後複製
登入後複製

正確的結果是0:

来挑战下这十个 Python 问题,你会吗?

這個不難,因為Python 的函數定義其實是可執行語句,函數在被呼叫前都是不存在的,實際呼叫時才會綁定變數。

在上面的範例中,在函數定義期間,Python 允許引用尚未定義的類別或函數。但是,在執行期間,A 已經是 int 類,這意味著函數方法將傳回一個新建立的 int 實例,int 實例的預設值就是 0。

如果沒有A = int,結果就是:

来挑战下这十个 Python 问题,你会吗?

#2.四捨五入

>>> round(7/2)
4
>>> round(3/2)
2
>>> round(5/2)
2
登入後複製

正確的結果是4 2 2,你肯定覺得最後的round(2.5) == 2 有點違反數學規則,這是因為Python 的round 方法實現了銀行家的四捨五入[1],其中所有半值將四捨五入到最接近的偶數。

3.type 和object

>>> isinstance(type, object)
True
>>> isinstance(object, type)
True
>>> isinstance(object, object)
True
>>> isinstance(type, type)
True
>>>
登入後複製

都是True,有點懷疑object 和true 是不是一個東西?

在Python 中,一切都是對象,因此對對象的任何實例檢查都會傳回True。

isinstance(Anything, object) #=> True。
登入後複製

type 表示用來建構所有 Python 類型的元類別。因此,所有類型:int、str、object 都是 type 類別的實例,就像 python 中的所有物件一樣,它也是一個物件。但 type 是 Python 中唯一的是它自己的一個實例的物件。

>>> type(1)
<class 'int'>
>>> type(int)
<class 'type'>
>>> type(type)
<class 'type'>
>>> 
登入後複製

4.空的布林值

>>> any([])
False
>>> all([])
True
>>> any([True,False])
True
>>> all([True,False])
False
>>> 
登入後複製

當參數是空列表的時候,any 和 all 的結果有點出乎意料。但明白了它的檢查邏輯,就合情合理了:

Python 中的邏輯運算子是惰性的,any 的演算法是尋找第一次出現為真元素,如果沒有找到,則傳回False,由於序列為空,因此沒有元素可以為真,因此any([]) 傳回False。

同樣的,all 演算法是查找第一個false 元素,如果沒有找到,則返回True,由於空序列中沒有假元素,所以all([]) 返回True,是不是有點空洞真理概念?

5.類別內部函數的優先權

class A:
answer = 42
def __init__(self):
self.answer = 21
self.__add__ = lambda x, y: x.answer + y
def __add__(self, y):
return self.answer - y
print(A() + 5)
登入後複製
登入後複製

正確的結果是:16:

来挑战下这十个 Python 问题,你会吗?

##物件函數的查找順序是:實例級別> 類別級別> 父類別級別,上面的程式碼,初始化時綁定的函數就是實例級別,在類別內部定義的就是類別級別。

但雙底線包裹的魔法函數不在這個規則之內,也就是說 Python 優先查找類別層級的魔法函數。

如果說把雙底線去掉,那麼結果就是26 啦:

来挑战下这十个 Python 问题,你会吗?

6

.求和
>>> sum("")
0
>>> sum("", [])
[]
>>> sum("", {})
{}
登入後複製

為了搞清楚這裡發生了什麼,我們需要檢查sum 函數的簽章:

sum(iterable, /, start=0)
登入後複製

sum 從左到右開始求和可迭代的項目,並傳回總數。 iterable 一般是數字,起始值不允許是字串。

在上述所有情況下,空字串都被視為空序列,因此 sum 將簡單地將起始參數作為總結果傳回。在第一種情況下,它預設為零,對於第二種和第三種情況,它意味著空列表和字典作為開始參數傳入。

7

.意外的屬性
>>> sum([
... el.imag
... for el in [
... 0, 5, 10e9, float('inf'), float('nan')
... ]
... ])
0.0
登入後複製

上面的程式碼有個imag 屬性,但是我們根本沒有定義它,運行也沒有報錯,怎麼回事呢?

這是因為Python 中的所有數值類型(int、real、float)都繼承自基底物件類,它們都支援real 和imag 屬性,分別傳回實部和虛部。這也包括 Infinity 和 NaN。

8.输出负数倍的字符串

>>> "this is a very long string" * (-1)
''
>>>
登入後複製

正确的结果是 '',所有的负数倍的字符串,都当作 0 倍,返回 ''。

9.见过负数的 0.0

max(-0.0, 0.0)
登入後複製
登入後複製

为什么会这样?出现这种情况是由于两个原因。负零和零在 Python 中被视为相等。max 的逻辑是,如果多个最大值,返回遇到的第一个。因此 max 函数返回第一次出现的零,它恰好是负数。

10.违反数学规则

>>> x = (1 << 53) + 1
>>> x + 1.0 > x
False
登入後複製

正确的结果是 False,这违反了数学规则啊,为什么呢?

这种违反直觉的行为归咎于三件事:长算术、浮点精度限制和数值比较。

Python 可以支持非常大的整数,如果隐式超过限制则切换计算模式,但 Python 中的浮点精度是有限的。

2⁵³ + 1 = 9007199254740993
登入後複製

是不能完全表示为 Python 浮点数的最小整数。因此,为了执行加 1.0,Python 将 9007199254740993 转换为 float,将其四舍五入为 Python 可以表示的 9007199254740992.0,然后向其添加 1.0,但由于相同的表示限制,它将其设置回 9007199254740992.0:

>>> float(9007199254740993)
9007199254740992.0
>>> 9007199254740992.0 + 1.0
9007199254740992.0
>>>
登入後複製

此外 Python 在 float 与 int 比较时并不会抛出错误,也不会尝试将两个操作数转换为相同的类型。相反,他们比较实际的数值。因为 9007199254740992.0 比 9007199254740993 小,因此 Python 返回 False。

以上是來挑戰下這十個 Python 問題,你會嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:51cto.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!