Python 經典面試題(一)


一、浮點數運算

題目

判斷浮點數的運行結果是否相等:

 a = 0.1
 b = 0.2
 c = 0.3
 assert a + b == c

題目解析:

本題考查的是計算機的浮點運算知識點。不僅是 python 語言,其他的編程語言也面臨同樣的問題:在進行浮點運算的時候,10 進制表示方式會丟掉它的精度,造成運算結果與實際結果不符合。

這是由於底層 CPU 和運算標准通過自己的浮點單位去執行算術時的特征決定的。看似有窮的小數, 在計算機的二進制表示里卻是無窮的。

所以在進行高進度浮點運算的時候一定要注意,尤其是自動化測試過程中需要進行斷言非常容易出錯。

題目答案:

斷言失敗,拋出 AssertionError 錯誤。

解決方案:

使用 Decimal 模塊:

 from decimal import Decimal
 
 a = 0.1
 b = 0.2
 c = 0.3
 assert Decimal(str(a)) + Decimal(str(b)) == Decimal(str(c))

Decimal() 可以維持浮點數的精度,在金融領域和測試領域等精度要求高的行業有非常大的作用。 但是一定要注意: Decimal() 傳的參數一定要是字符串類型,如果是數據類型會再次丟掉精度。

  Decimal(0.1) + Decimal(0.2) == Decimal(0.3)  # False
  Decimal('0.1') + Decimal('0.2') == Decimal('0.3') # True

二、列表的扁平化和降維

題目

有一個二維列表,降成普通的一維的。比如說檸檬班都會有學員分組,我們想通過分組信息去獲取所有的學員名稱。

 groups = [['huahua', 'xiaojian'], ['musen', 'yuze'], ['keyou']]
 # 得到結果 ['huahua', 'xiaojian', 'musen', 'yuze', 'keyou']

方法一

最簡單的方式可以通過 for 循環的方式一一提取:

 names = []
 for group in groups:
  for name in group:
  names.append(name)
 print(names)

方法二

但是在面試的時候可能會加一些限制,比如讓你用一行代碼實現,這個時候就需要對 python 基礎有進一步的理解了,比如說使用 sum 函數:

 names = sum(groups, [])

非常簡單就實現了同樣的功能。 sum 函數為什么可以做到呢?先看一個簡單的例子:

 a = sum([1,2,3])

得到的結果是 6, 也就是說, sum 函數會把一個列表里面的每個元素相加。但是 sum 函數還可以有第二個參數:開始值,默認為 0 , 所以上述過程其實可以寫成:

 a = sum([1,2,3], 0)
 # 0 + 1 + 2 + 3

依據同樣的道理,可以對列表進行降維操作:

a = sum([['yuze'], ['is'], ['a']], [])
# [] + ['yuze'] + ['is'] + ['a']
# 列表拼接

方法三

通過列表推導式也可以方便的解決:

a = [e for group in groups for e in group]

三、多重繼承

class A:
    def run(self):
        print("a is running")

class B:
    def run(self):
        print("b is running")

class C(A, B):
    pass

# 會打印什么???
C().run()

多重繼承經常用來出面試題。在這個考題中,C 類的父類 A 和 B 都實現了 run 方法,那在 C 的對象里到底是優先調用哪一個呢?

答案是: a running

菱形問題

class A:
    def run(self):
        print("a running")

class B(A):
    pass

class C(A):
    def run(self):
        print("C running")

class D(B, C):
    pass

# 會打印什么???
D().run()

他們的繼承關系圖可以簡化如下,這個問題又稱為菱形問題或者鑽石問題:

 

 

答案是: c running

如果我們不讓 C 類繼承 A 呢?

class A:
    def run(self):
        print("a running")

class B(A):
    pass

class C:
    def run(self):
        print("C running")

class D(B, C):
    pass

# 會打印什么???
D().run()

他們的繼承關系圖可以簡化如下,可以簡稱為 v 型問題:

 

答案會變成 a running

題目解析

具體原因是 python 的繼承會遵循特定的順序,優先級排在前面的,子類會優先使用。怎么快速查看這種繼承順序呢?通過D.__mro__去查看

比如在 菱形問題上,d 的順序是這樣的:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

D 排在最前面,如果 D 定義了 run 方法,就會被優先使用,然后是 B, 然后是C, 然后是 A, 最后是 object 基類。

而在 V 行問題上,d 的順序又變成了這樣:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>, <class 'object'>)

A 和 C 互換了順序。造成 2 個題目的答案不一致。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM