熱線電話:13121318867

登錄
首頁精彩閱讀職場經驗之15個你必須知道的Python面試題
職場經驗之15個你必須知道的Python面試題
2019-07-04
收藏
職場經驗之15個你必須知道的Python面試題

介紹

隨著人工智能、機器學習、深度學習的發展,這個領域也正在不斷的進入人們的眼簾,并且帶來了很多、很大的工作機會,隨著這些機會的誕生,Python在這個機會中也在不斷的發展壯大,因為Python不像其他語言一樣復雜,Python簡單易學容易被人們接受。并且這并不是我一個人在這里瞎說就可以證明的,在2019年6月PYPL流行程序設計語言中,Python排在第一位占到了28.08%,是第二名Java和第三名Javascript的和,并且還在不斷的上漲中。

職場經驗之15個你必須知道的Python面試題

而且在另外一個編程語言TIOBE指數排行榜中,Python排在了第三位,排在第一位和第二位的是Java和C語言。并且排行榜還預測認為Python會在3-4年取代C和Java,而原因是軟件工程行業正在不斷的蓬勃發展,吸引了很多新人進入該領域,Java和C對于初學者來說一些困難,而Python相對于這兩種語言來說,太過于簡單了。

職場經驗之15個你必須知道的Python面試題

站在這里,我認為現在正在看這篇文章的你想要找一份有關于Python的工作,不然你也不會點進來不是,你可能是一個Python的初學者,或者說已經在Python工作崗位上已經工作過了,但是如果你還需要找一份Python的工作的話,你可能需要證明你知道如何使用Python。以下是一些涉及與Python相關的基礎技能的問題。重點放在語言本身,而不是任何特定的包或框架。

某種程度上來說,我還沒有遇到過這么難的面試,如果你能輕松的答對這些問題,找到正確的答案,那么就快去找份工作吧。

本教程不是固定指南

本教程不打算涵蓋所有的工作場所因為不同的雇主會以不同的方式向你提出不同的問題; 他們會有各自的習慣; 他們重視的內容也是不同的。他們會以不同的方式測試你。有些老板會讓你坐在電腦前,要求你解決簡單的問題; 有些會讓你在白板前站起來做類似的事; 有些人會給你一個需要讓你回家解決的問題,方便節省他們的時間;而還有些人會和你談談。

而對程序員的最佳測試實際上就是編程。使用簡單的教程測試是一件困難的事情。因此,為了面試過程中的加分,請確保你真的掌握了解決問題的方法。如果你真的很明白這些方法,那么你就可以利用解決問題的方法,使你獲得勝利。

同樣的,對于軟件工程師的最有效的測試實際上是工程學。本教程是關于Python作為一種語言。能夠設計高效,有效,可維護的類層次結構來解決小眾問題是非常了不起的,并且是一項值得追求的技能,但是這就超出了本文的范圍。

本教程不符合PEP8標準。這是有意的,因為如前所述,不同的老板將遵循不同的習慣。你需要適應公司的文化。因為實用性勝過一切。

本教程另一個不足之處是不夠簡潔。我不想只是向你提出問題和答案,而是希望有些事情可以解決。我希望你能夠理解,或者至少理解的足夠好,這樣你們對任何有問題的話題能夠進一步的去解釋

問題1

Python到底是什么,你可以在回答中與其他技術進行比較(加分項)。

回答

以下是幾個要點:

  • Python是一種解釋型語言。這意味著,與C語言及其變體等語言不同,Python不需要在運行之前進行編譯。其他解釋語言包括PHPRuby。
  • Python是動態類型的,這意味著當你聲明變量或類似的變量時,你不需要聲明變量的類型。你可以做先一些事情如:x=111,然后再將x="I'm a string"這樣并沒有錯誤
  • Python非常適合面向對象的編程,因為它允許類的定義以及組合和繼承。Python沒有訪問修飾符(如C ++的public,private),對于這一點的理由是因為‘我們都是成年人’
  • 在Python中,函數也是一個類對象。這意味著可以將它們分配給變量,從其他函數返回并傳遞給函數。類也是一個類對象
  • 編寫Python代碼可以很快,但運行它通常比編譯語言慢。但幸運的是,Python允許包含基于C的擴展,因此瓶頸可以被優化掉并且可以經常被優化。這個numpy包就是一個很好的例子,它真的非???,因為它處理的很多數字運算實際上并不是由Python完成的
  • Python可用于許多領域 - Web應用程序,自動化,科學建模,大數據應用程序等等。它也經常被用作“粘合”代碼,以使其他語言和組件發揮得很好。
  • Python使得困難的事情變得容易,因此程序員可以專注于重寫算法和結構,而不是關注底層的低級細節。
職場經驗之15個你必須知道的Python面試題

為什么這很重要:

如果你正在申請的是Python職位,你應該知道它是什么以及為什么它如此酷。

問題2

填寫遺漏的代碼:

def print_directory_contents(sPath):

"""

這個函數接受一個目錄的名稱

并且打印該目錄中的路徑文件

包含目錄以及目錄中的任何文件

這個函數類似于os.walk。

但是請不要使用這個模塊系統。

輸入你的答案

我們對你使用嵌套結構的能力很感興趣

"""

fill_this_in

回答

def print_directory_contents(sPath):

import os

for sChild in os.listdir(sPath):

sChildPath = os.path.join(sPath,sChild)

if os.path.isdir(sChildPath):

print_directory_contents(sChildPath)

else:

print(sChildPath)

職場經驗之15個你必須知道的Python面試題

特別注意

  • 與你的命名約定保持一致。如果在任何示例代碼中都有明顯的命名約定,請堅持下去。即使它不是你通常使用的命名約定
  • 遞歸函數需要遞歸和終止。確認你真的了解這是如何發生的,這樣你就可以避免無底的調用堆棧
  • 我們使用該os模塊以跨平臺的方式與操作系統進行交互。你可以說,sChildPath = sPath + '/' + sChild但這不適用于Windows
  • 熟悉基本的軟件包是非常值得的,但是不要為了記住所有的東西而頭痛,百度or谷歌是你在工作中遇到需要包的問題的時候的朋友!
  • 如果你不理解代碼應該做什么,請提出問題
  • 保持簡單,笨蛋!

為什么這很重要:

  • 顯示你的基本操作系統交互內容方面的知識
  • 遞歸是非常有用的

問題3

查看下面的代碼,寫下A0,A1,...An的最終值。

A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))

A1 = range(10)

A2 = sorted([i for i in A1 if i in A0])

A3 = sorted([A0[s] for s in A0])

A4 = [i for i in A1 if i in A3]

A5 = {i:i*i for i in A1}

A6 = [[i,i*i] for i in A1]

如果你不知道什么是zip那么不用緊張。沒有一個理智的雇主會要求你熟記標準庫。這是help(zip)的輸出。

zip(...)

zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]

Return a list of tuples, where each tuple contains the i-th element

from each of the argument sequences. The returned list is truncated

in length to the length of the shortest argument sequence.

如果這沒有任何意義,那么就請你花幾分鐘去想清楚你要選擇的方式。

回答

A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4} # the order may vary

A1 = range(0, 10) # or [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] in python 2

A2 = []

A3 = [1, 2, 3, 4, 5]

A4 = [1, 2, 3, 4, 5]

A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

為什么這很重要

  1. 對于很多人來說,理解列表是一個很好的節省時間的方法,當然也是一個巨大的絆腳石
  2. 如果你能讀懂它們,那么你也可以寫下來
  3. 這些代碼中的一部分是故意設計的很奇怪的。因為你可能需要在工作中與一些奇怪的人合作
職場經驗之15個你必須知道的Python面試題

問題4

多線程使用Python。這是個好主意嗎?列出一些方法可以讓一些Python代碼以并行方式運行。

回答

Python不允許真正意義上的多線程。它有一個多線程包,但如果你想使用多線程來加速你的代碼,那么使用它通常不是一個好主意。Python有一個名為全局解釋器鎖(Global Interpreter Lock(GIL))的結構。GIL確保每次只能執行一個“線程”。一個線程獲取GIL,做一點工作,然后將GIL傳遞到下一個線程。這種情況發生的很快,因此對于人眼看來,你的線程似乎是并行運行的,但它們實際上只是輪流使用相同的CPU核心。所有這些GIL傳遞都增加了運行的內存。這意味著如果你想讓代碼運行得更快,那么使用線程包通常不是一個好主意。

使用Python的線程包也是有原因的。如果你想同時運行一些東西,并且效率不是一個問題,那么它就完全沒問題了?;蛘?,如果你正在運行需要等待某些事情的代碼(例如某些IO),那么它可能會很有意義。但是線程庫不會讓你使用額外的CPU核心。

多線程可以外包到操作系統(通過多處理),一些調用Python代碼的外部應用程序(例如,Spark或Hadoop),或者Python代碼調用的一些代碼例如:你可以使用你的Python代碼調用一個C函數來完成昂貴的多線程事務。

為什么這很重要

因為GIL是一個A-hole。在學習GIL之前,很多人花了很多的時間在他們的Python多線程中遇到了瓶頸。

問題5

如何跟蹤代碼的不同版本?

回答:

版本控制!此時,你應該表現的非常興奮,并告訴他們你如何使用Git(或任何你最喜歡的)來跟蹤與Granny的通信。Git是我首選的版本控制系統,但還有其他版本控制系統,例如subversion。

為什么這很重要:

因為沒有版本控制的代碼就像沒有杯子的咖啡。有時我們需要編寫一次性丟棄的腳本,這沒關系,但是如果你正在處理大量的代碼,版本控制系統將是一個優勢。版本控制有助于跟蹤誰對代碼庫進行了哪些更改; 找出Bug是什么時候引入代碼的; 跟蹤軟件的版本和發布版本; 在團隊成員之間分發源代碼; 部署和某些自動化。它允許你在破壞代碼之前將代碼轉回到自己的代碼之上。等等很多東西。這太棒了。

問題6

這段代碼輸出了什么:

def f(x,l=[]):

for i in range(x):

l.append(i*i)

print(l)

f(2)

f(3,[3,2,1])

f(3)

回答

[0, 1]

[3, 2, 1, 0, 1, 4]

[0, 1, 0, 1, 4]

為什么重要?

第一個函數調用應該相當明顯,循環將0和1附加到空列表中l.l是指向存儲在內存中的列表的變量的名稱。 第二個調用通過在新的內存塊中創建新列表開始。l然后指向這個新列表。然后它將0,1和4附加到這個新列表中。這太好了。 第三個函數調用是奇怪的。它使用存儲在原始內存塊中的原始列表。這就是它從0和1開始的原因。

如果你不明白,試試這個:

l_mem = []

l = l_mem # the first call

for i in range(2):

l.append(i*i)

print(l) # [0, 1]

l = [3,2,1] # the second call

for i in range(3):

l.append(i*i)

print(l) # [3, 2, 1, 0, 1, 4]

l = l_mem # the third call

for i in range(3):

l.append(i*i)

print(l) # [0, 1, 0, 1, 4]

問題7

什么是猴子補???,這是個好主意嗎?

回答

猴子補丁是在定義函數或對象已經定義后進行更改的行為。例如:

import datetime

datetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)

大多數時候,這是一個非常糟糕的想法 - 如果事情以明確的方式運行,通常是最好的。猴子補丁的一個原因是測試。該模擬包對此還是非常有用的。

為什么這很重要

它表明你對單元測試中的方法有所了解。你提到避免使用猴子補丁會表明你不是那些喜歡花哨的代碼而不喜歡可維護代碼的程序員(他們就在那里,而且合作起來會非常糟糕)。它表明你對Python如何在較低層次上工作,如何實際存儲和調用函數等有所了解。

問題8

這是什么東西的意思是:*args,**kwargs?我們為什么要用它呢?

回答

當我們不確定要向函數傳遞多少參數時,或者我們想向函數傳遞已存儲的列表或參數元組時使用*args。**kwargs用于當我們不知道將多少關鍵字參數傳遞給函數時,或者它可以用用于關鍵字參數傳遞字典的值。標識符args和kwargs是一種約定,你也可以使用*bob,**billy但這不是明智的。

這是一個小示例:

def f(*args,**kwargs): print(args, kwargs)

l = [1,2,3]

t = (4,5,6)

d = {'a':7,'b':8,'c':9}

f()

f(1,2,3) # (1, 2, 3) {}

f(1,2,3,"groovy") # (1, 2, 3, 'groovy') {}

f(a=1,b=2,c=3) # () {'a': 1, 'c': 3, 'b': 2}

f(a=1,b=2,c=3,zzz="hi") # () {'a': 1, 'c': 3, 'b': 2, 'zzz': 'hi'}

f(1,2,3,a=1,b=2,c=3) # (1, 2, 3) {'a': 1, 'c': 3, 'b': 2}

f(*l,**d) # (1, 2, 3) {'a': 7, 'c': 9, 'b': 8}

f(*t,**d) # (4, 5, 6) {'a': 7, 'c': 9, 'b': 8}

f(1,2,*t) # (1, 2, 4, 5, 6) {}

f(q="winning",**d) # () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}

f(1,2,*t,q="winning",**d) # (1, 2, 4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}

def f2(arg1,arg2,*args,**kwargs): print(arg1,arg2, args, kwargs)

f2(1,2,3) # 1 2 (3,) {}

f2(1,2,3,"groovy") # 1 2 (3, 'groovy') {}

f2(arg1=1,arg2=2,c=3) # 1 2 () {'c': 3}

f2(arg1=1,arg2=2,c=3,zzz="hi") # 1 2 () {'c': 3, 'zzz': 'hi'}

f2(1,2,3,a=1,b=2,c=3) # 1 2 (3,) {'a': 1, 'c': 3, 'b': 2}

f2(*l,**d) # 1 2 (3,) {'a': 7, 'c': 9, 'b': 8}

f2(*t,**d) # 4 5 (6,) {'a': 7, 'c': 9, 'b': 8}

f2(1,2,*t) # 1 2 (4, 5, 6) {}

f2(1,1,q="winning",**d) # 1 1 () {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}

f2(1,2,*t,q="winning",**d) # 1 2 (4, 5, 6) {'a': 7, 'q': 'winning', 'c': 9, 'b': 8}

為什么關心?

有時我們需要將未知數量的參數或關鍵字參數傳遞給函數。有時我們會想要存儲參數或關鍵字參數供以后使用。有時它只是節省時間。

問題9

這些對你來說意味著:@classmethod,@staticmethod,@property?

回答背景知識

這些是裝飾者。裝飾器是一種特殊的函數,它既可以獲取函數并可以返回一個函數,或者獲取一個類并返回一個類。該@符號只是語法糖,允許你以一種易于閱讀的方式裝飾一些東西。

@my_decorator

def my_func(stuff):

do_things

相當于

def my_func(stuff):

do_things

my_func = my_decorator(my_func)

實際答案

裝飾器@classmethod,@staticmethod和@property是在類中定義的函數的時候使用。以下是他們的行為方式:

class MyClass(object):

def __init__(self):

self._some_property = "properties are nice"

self._some_other_property = "VERY nice"

def normal_method(*args,**kwargs):

print("calling normal_method({0},{1})".format(args,kwargs))

@classmethod

def class_method(*args,**kwargs):

print("calling class_method({0},{1})".format(args,kwargs))

@staticmethod

def static_method(*args,**kwargs):

print("calling static_method({0},{1})".format(args,kwargs))

@property

def some_property(self,*args,**kwargs):

print("calling some_property getter({0},{1},{2})".format(self,args,kwargs))

return self._some_property

@some_property.setter

def some_property(self,*args,**kwargs):

print("calling some_property setter({0},{1},{2})".format(self,args,kwargs))

self._some_property = args[0]

@property

def some_other_property(self,*args,**kwargs):

print("calling some_other_property getter({0},{1},{2})".format(self,args,kwargs))

return self._some_other_property

o = MyClass()

#未修飾方法的工作原理與普通方法一樣,它們將當前實例(self)作為第一個參數

o.normal_method

# >

o.normal_method()

# normal_method((<__main__.MyClass instance at 0x7fdd2537ea28>,),{})

o.normal_method(1,2,x=3,y=4)

# normal_method((<__main__.MyClass instance at 0x7fdd2537ea28>, 1, 2),{'y': 4, 'x': 3})

# class methods always get the class as the first argument

o.class_method

# >

o.class_method()

# class_method((,),{})

o.class_method(1,2,x=3,y=4)

# class_method((, 1, 2),{'y': 4, 'x': 3})

# static methods have no arguments except the ones you pass in when you call them

o.static_method

#

o.static_method()

# static_method((),{})

o.static_method(1,2,x=3,y=4)

# static_method((1, 2),{'y': 4, 'x': 3})

# properties are a way of implementing getters and setters. It's an error to explicitly call them

# "read only" attributes can be specified by creating a getter without a setter (as in some_other_property)

o.some_property

# calling some_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})

# 'properties are nice'

o.some_property()

# calling some_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})

# Traceback (most recent call last):

# File "", line 1, in

# TypeError: 'str' object is not callable

o.some_other_property

# calling some_other_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})

# 'VERY nice'

# o.some_other_property()

# calling some_other_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})

# Traceback (most recent call last):

# File "", line 1, in

# TypeError: 'str' object is not callable

o.some_property = "groovy"

# calling some_property setter(<__main__.MyClass object at 0x7fb2b7077890>,('groovy',),{})

o.some_property

# calling some_property getter(<__main__.MyClass object at 0x7fb2b7077890>,(),{})

# 'groovy'

o.some_other_property = "very groovy"

# Traceback (most recent call last):

# File "", line 1, in

# AttributeError: can't set attribute

o.some_other_property

# calling some_other_property getter(<__main__.MyClass object at 0x7fb2b7077890>,(),{})

# 'VERY nice'

職場經驗之15個你必須知道的Python面試題

問題10

想想下面這串代碼,它將輸出什么?

class A(object):

def go(self):

print("go A go!")

def stop(self):

print("stop A stop!")

def pause(self):

raise Exception("Not Implemented")

class B(A):

def go(self):

super(B, self).go()

print("go B go!")

class C(A):

def go(self):

super(C, self).go()

print("go C go!")

def stop(self):

super(C, self).stop()

print("stop C stop!")

class D(B,C):

def go(self):

super(D, self).go()

print("go D go!")

def stop(self):

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢