Python開發【面試】:刷題


面試題

1、到底什么是Python?

  • Python是一種解釋型語言。這就是說,與C語言和C的衍生語言不同,Python代碼在運行之前不需要編譯(一邊編寫一邊執行,先把代碼轉化成字節碼,然后python虛擬機去執行)。其他解釋型語言還包括PHP和Ruby
  • Python非常適合面向對象的編程(OOP),因為它支持通過組合(composition)與繼承(inheritance)的方式定義類(class)
  • Python代碼編寫快,但是運行速度比編譯語言通常要慢。好在Python允許加入基於C語言編寫的擴展,因此我們能夠優化代碼,消除瓶頸,這點通常是可以實現的
  • Python用途非常廣泛——網絡應用,自動化,科學建模,大數據應用,爬蟲等等。它也常被用作“膠水語言”,幫助其他語言和組件改善運行狀況
  • Python讓困難的事情變得容易,因此程序員可以專注於算法和數據結構的設計,而不用處理底層的細節

 

 2、補充缺失的代碼

def print_directory_contents(sPath):
    '''
   輸入文件夾的路徑(絕對和相對均可)
   打印文件夾里面包含的所有文件名(子子孫孫,帶完整的路徑)
    ''''
1 def print_directory_contents(sPath):
2     import os
3     for sChild in os.listdir(sPath):
4         sChild = os.path.join(sPath,sChild)
5         if os.path.isdir(sChild):
6             print_directory_contents(sChild)
7         else:
8             print(sChild)
答案.

 

3、閱讀下面的代碼,寫出A0,A1至An的最終值

  • A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
  • A1 = range(10)
  • A2 = [i for i in A1 if i in A0]
  • A3 = [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]
A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 3, 2, 5, 4]
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]]
答案.

 

4、Python和多線程(multi-threading)。這是個好主意碼?列舉一些讓Python代碼以並行方式運行的方法

Python並不支持真正意義上的多線程。Python中提供了多線程包,但是如果你想通過多線程提高代碼的速度,使用多線程包並不是個好主意。Python中有一個被稱為Global Interpreter Lock(GIL)的東西,它會確保任何時候你的多個線程中,只有一個被執行。線程的執行速度非常之快,會讓你誤以為線程是並行執行的,但是實際上都是輪流執行。經過GIL這一道關卡處理,會增加執行的開銷。這意味着,如果你想提高代碼的運行速度,使用threading包並不是一個很好的方法。

不過還是有很多理由促使我們使用threading包的。如果你想同時執行一些任務,而且不考慮效率問題,那么使用這個包是完全沒問題的,而且也很方便。但是大部分情況下,並不是這么一回事,你會希望把多線程的部分外包給操作系統完成(通過開啟多個進程),或者是某些調用你的Python代碼的外部程序(例如Spark或Hadoop),又或者是你的Python代碼調用的其他代碼(例如,你可以在Python中調用C函數,用於處理開銷較大的多線程工作)。

為什么提這個問題

因為GIL就是個混賬東西(A-hole)。很多人花費大量的時間,試圖尋找自己多線程代碼中的瓶頸,直到他們明白GIL的存在。

 

5、下面代碼會輸出什么:

def f(x,l=[]):
    for i in range(x):
        l.append(i*i)
    print l

f(2)
f(3,[3,2,1])
f(3)
1 [0, 1]
2 [3, 2, 1, 0, 1, 4]
3 [0, 1, 0, 1, 4]
答案.

 

6、“猴子補丁”(monkey patching)指的是什么?這種做法好嗎?

“猴子補丁”就是指,在函數或對象已經定義之后,再去改變它們的行為。

舉個例子:

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

大部分情況下,這是種很不好的做法 - 因為函數在代碼庫中的行為最好是都保持一致。打“猴子補丁”的原因可能是為了測試。mock包對實現這個目的很有幫助。

 

7、這兩個參數是什么意思:*args**kwargs?我們為什么要使用它們

如果我們不確定要往函數中傳入多少個參數,或者我們想往函數中以列表和元組的形式傳參數時,那就使要用*args;如果我們不知道要往函數中傳入多少個關鍵詞參數,或者想傳入字典的值作為關鍵詞參數時,那就要使用**kwargsargskwargs這兩個標識符是約定俗成的用法,你當然還可以用*bob**billy,但是這樣就並不太妥

 

8、閱讀下面的代碼,它的輸出結果是什么?

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):
        super(D, self).stop()
        print "stop D stop!"
    def pause(self):
        print "wait D wait!"

class E(B,C): pass

a = A()
b = B()
c = C()
d = D()
e = E()

# 說明下列代碼的輸出結果

a.go()
b.go()
c.go()
d.go()
e.go()

a.stop()
b.stop()
c.stop()
d.stop()
e.stop()

a.pause()
b.pause()
c.pause()
d.pause()
e.pause()
輸出結果以注釋的形式表示:

a.go()
# go A go!

b.go()
# go A go!
# go B go!

c.go()
# go A go!
# go C go!

d.go()
# go A go!
# go C go!
# go B go!
# go D go!

e.go()
# go A go!
# go C go!
# go B go!

a.stop()
# stop A stop!

b.stop()
# stop A stop!

c.stop()
# stop A stop!
# stop C stop!

d.stop()
# stop A stop!
# stop C stop!
# stop D stop!

e.stop()
# stop A stop!

a.pause()
# ... Exception: Not Implemented

b.pause()
# ... Exception: Not Implemented

c.pause()
# ... Exception: Not Implemented

d.pause()
# wait D wait!

e.pause()
# ...Exception: Not Implemented
答案

 

9、閱讀下面的代碼,它的輸出結果是什么?

class Node(object):
    def __init__(self,sName):
        self._lChildren = []
        self.sName = sName
    def __repr__(self):
        return "<Node '{}'>".format(self.sName)
    def append(self,*args,**kwargs):
        self._lChildren.append(*args,**kwargs)
    def print_all_1(self):
        print self
        for oChild in self._lChildren:
            oChild.print_all_1()
    def print_all_2(self):
        def gen(o):
            lAll = [o,]
            while lAll:
                oNext = lAll.pop(0)
                lAll.extend(oNext._lChildren)
                yield oNext
        for oNode in gen(self):
            print oNode

oRoot = Node("root")
oChild1 = Node("child1")
oChild2 = Node("child2")
oChild3 = Node("child3")
oChild4 = Node("child4")
oChild5 = Node("child5")
oChild6 = Node("child6")
oChild7 = Node("child7")
oChild8 = Node("child8")
oChild9 = Node("child9")
oChild10 = Node("child10")

oRoot.append(oChild1)
oRoot.append(oChild2)
oRoot.append(oChild3)
oChild1.append(oChild4)
oChild1.append(oChild5)
oChild2.append(oChild6)
oChild4.append(oChild7)
oChild3.append(oChild8)
oChild3.append(oChild9)
oChild6.append(oChild10)

# 說明下面代碼的輸出結果

oRoot.print_all_1()
oRoot.print_all_2()
 1 oRoot.print_all_1()會打印下面的結果:
 2 
 3 <Node 'root'>
 4 <Node 'child1'>
 5 <Node 'child4'>
 6 <Node 'child7'>
 7 <Node 'child5'>
 8 <Node 'child2'>
 9 <Node 'child6'>
10 <Node 'child10'>
11 <Node 'child3'>
12 <Node 'child8'>
13 <Node 'child9'>
14 oRoot.print_all_1()會打印下面的結果:
15 
16 <Node 'root'>
17 <Node 'child1'>
18 <Node 'child2'>
19 <Node 'child3'>
20 <Node 'child4'>
21 <Node 'child5'>
22 <Node 'child6'>
23 <Node 'child8'>
24 <Node 'child9'>
25 <Node 'child7'>
26 <Node 'child10'>
答案.

 

10、簡要描述Python的垃圾回收機制(garbage collection) 

  • Python在內存中存儲了每個對象的引用計數(reference count)。如果計數值變成0,那么相應的對象就會小時,分配給該對象的內存就會釋放出來用作他用。
  • 偶爾也會出現引用循環(reference cycle)。垃圾回收器會定時尋找這個循環,並將其回收。舉個例子,假設有兩個對象o1o2,而且符合o1.x == o2o2.x == o1這兩個條件。如果o1o2沒有其他代碼引用,那么它們就不應該繼續存在。但它們的引用計數都是1。
  • Python中使用了某些啟發式算法(heuristics)來加速垃圾回收。例如,越晚創建的對象更有可能被回收。對象被創建之后,垃圾回收器會分配它們所屬的代(generation)。每個對象都會被分配一個代,而被分配更年輕代的對象是優先被處理的。

  

 

  

 


免責聲明!

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



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