你好,我是徵哥,Python 很容易入門,但卻不易精通,即使有經驗的工程師,某些現像也是反直覺的,以下這10 個問題就非常有趣,且有一定的挑戰性,結果可能會讓你感到困惑,來看看你能回答正確幾個?
這裡先給出題目,最後給出答案,建議先拿個紙,寫下你的答案,最後再驗證。
請寫出以下程式碼的輸出結果:
class A: def function(self): return A() a = A() A = int print(a.function())
>>> round(7 / 2) >>> round(3 / 2) >>> round(5 / 2)
>>> isinstance(type, object) >>> isinstance(object, type) >>> isinstance(object, object) >>> isinstance(type, type)
>>> any([]) >>> all([])
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)
>>> sum("") >>> sum("", []) >>> sum("", {})
>>> sum([ el.imag for el in [ 0, 5, 10e9, float('inf'), float('nan') ] ])
>>> "this is a very long string" * (-1)
max(-0.0, 0.0)
>>> x = (1 << 53) + 1 >>> x + 1.0 > x
以下結果皆在Python 3.8.5 版本驗證。
class A: def function(self): return A() a = A() A = int print(a.function())
正確的結果是0:
這個不難,因為Python 的函數定義其實是可執行語句,函數在被呼叫前都是不存在的,實際呼叫時才會綁定變數。
在上面的範例中,在函數定義期間,Python 允許引用尚未定義的類別或函數。但是,在執行期間,A 已經是 int 類,這意味著函數方法將傳回一個新建立的 int 實例,int 實例的預設值就是 0。
如果沒有A = int,結果就是:
>>> round(7/2) 4 >>> round(3/2) 2 >>> round(5/2) 2
正確的結果是4 2 2,你肯定覺得最後的round(2.5) == 2 有點違反數學規則,這是因為Python 的round 方法實現了銀行家的四捨五入[1],其中所有半值將四捨五入到最接近的偶數。
>>> 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'> >>>
>>> any([]) False >>> all([]) True >>> any([True,False]) True >>> all([True,False]) False >>>
當參數是空列表的時候,any 和 all 的結果有點出乎意料。但明白了它的檢查邏輯,就合情合理了:
Python 中的邏輯運算子是惰性的,any 的演算法是尋找第一次出現為真元素,如果沒有找到,則傳回False,由於序列為空,因此沒有元素可以為真,因此any([]) 傳回False。
同樣的,all 演算法是查找第一個false 元素,如果沒有找到,則返回True,由於空序列中沒有假元素,所以all([]) 返回True,是不是有點空洞真理概念?
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 優先查找類別層級的魔法函數。 如果說把雙底線去掉,那麼結果就是26 啦:6>>> sum("") 0 >>> sum("", []) [] >>> sum("", {}) {}
sum(iterable, /, start=0)
>>> sum([ ... el.imag ... for el in [ ... 0, 5, 10e9, float('inf'), float('nan') ... ] ... ]) 0.0
>>> "this is a very long string" * (-1) '' >>>
正确的结果是 '',所有的负数倍的字符串,都当作 0 倍,返回 ''。
max(-0.0, 0.0)
为什么会这样?出现这种情况是由于两个原因。负零和零在 Python 中被视为相等。max 的逻辑是,如果多个最大值,返回遇到的第一个。因此 max 函数返回第一次出现的零,它恰好是负数。
>>> 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中文網其他相關文章!