1. 程式人生 > >整理面試題(二)

整理面試題(二)

1.以下程式碼將輸出什麼? list = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’] print list[10:] 答案 以上程式碼將輸出 [],並且不會導致一個 IndexError。

正如人們所期望的,試圖訪問一個超過列表索引值的成員將導致 IndexError(比如訪問以上列表的 list[10])。儘管如此,試圖訪問一個列表的以超出列表成員數作為開始索引的切片將不會導致 IndexError,並且將僅僅返回一個空列表。

一個討厭的小問題是它會導致出現 bug ,並且這個問題是難以追蹤的,因為它在執行時不會引發錯誤。

2.以下的程式碼的輸出將是什麼? 說出你的答案並解釋?

def multipliers():
    return [lambda x : i * x for i in range(4)]

print([m(2) for m in multipliers()])

你將如何修改 multipliers 的定義來產生期望的結果

答案

以上程式碼的輸出是 [6, 6, 6, 6] (而不是 [0, 2, 4, 6])。

這個的原因是 Python 的閉包的後期繫結導致的 late binding,這意味著在閉包中的變數是在內部函式被呼叫的時候被查詢。所以結果是,當任何 multipliers() 返回的函式被呼叫,在那時,i 的值是在它被呼叫時的周圍作用域中查詢,到那時,無論哪個返回的函式被呼叫,for 迴圈都已經完成了,i 最後的值是 3,因此,每個返回的函式 multiplies 的值都是 3。因此一個等於 2 的值被傳遞進以上程式碼,它們將返回一個值 6 (比如: 3 x 2)。

(順便說下,正如在 The Hitchhiker’s Guide to Python 中指出的,這裡有一點普遍的誤解,是關於 lambda 表示式的一些東西。一個 lambda 表示式建立的函式不是特殊的,和使用一個普通的 def 建立的函式展示的表現是一樣的。)

這裡有兩種方法解決這個問題。

最普遍的解決方案是建立一個閉包,通過使用預設引數立即繫結它的引數。例如:

def multipliers():
    return [lambda x, i=i : i * x for i in range(4)]

另外一個選擇是,你可以使用 functools.partial 函式:

from
functools import partial from operator import mul def multipliers(): return [partial(mul, i) for i in range(4)]

3.以下的程式碼的輸出將是什麼? 說出你的答案並解釋?

def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)

以上程式碼的輸出為:

list1 = [10, ‘a’] list2 = [123] list3 = [10, ‘a’] 許多人會錯誤的認為 list1 應該等於 [10] 以及 list3 應該等於 [‘a’]。認為 list 的引數會在 extendList 每次被呼叫的時候會被設定成它的預設值 []。

儘管如此,實際發生的事情是,新的預設列表僅僅只在函式被定義時建立一次。隨後當 extendList 沒有被指定的列表引數呼叫的時候,其使用的是同一個列表。這就是為什麼當函式被定義的時候,表示式是用預設引數被計算,而不是它被呼叫的時候。

因此,list1 和 list3 是操作的相同的列表。而 `list2是操作的它建立的獨立的列表(通過傳遞它自己的空列表作為list 引數的值)。 extendList 函式的定義可以做如下修改,但,當沒有新的 list 引數被指定的時候,會總是開始一個新列表,這更加可能是一直期望的行為。

def extendList(val, list=None):
    if list is None:
        list = []
    list.append(val)
    return list

使用這個改進的實現,輸出將是:

list1 = [10] list2 = [123] list3 = [‘a’]

4.Python自省 自省就是面向物件的語言所寫的程式在執行時,就能知道物件的型別。也就是程式執行時能夠獲得物件的型別。比如type(),dir(),getattr(),hasattr(),isinstance()。

a = [1, 2, 3]
b = {'a':1, 'b':2, 'c':3}
c = True

print(type(a), type(b), type(c)) 
print(isinstance(a, list))  

# <class 'list'> <class 'dict'> <class 'bool'>
# True

5.三次握手,四次揮手 1 三次握手

客戶端通過向伺服器端傳送一個SYN來建立一個主動開啟,作為三次握手的一部分。客戶端把這段連線的序號設定為隨機數 A。 伺服器端應當為一個合法的SYN回送一個SYN/ACK。ACK 的確認碼應為 A+1,SYN/ACK 包本身又有一個隨機序號 B。 最後,客戶端再發送一個ACK。當服務端受到這個ACK的時候,就完成了三路握手,並進入了連線建立狀態。此時包序號被設定為收到的確認號 A+1,而響應則為 B+1。 2 四次揮手

注意: 中斷連線端可以是客戶端,也可以是伺服器端. 下面僅以客戶端斷開連線舉例, 反之亦然.

客戶端傳送一個數據分段, 其中的 FIN 標記設定為1. 客戶端進入 FIN-WAIT 狀態. 該狀態下客戶端只接收資料, 不再發送資料. 伺服器接收到帶有 FIN = 1 的資料分段, 傳送帶有 ACK = 1 的剩餘資料分段, 確認收到客戶端發來的 FIN 資訊. 伺服器等到所有資料傳輸結束, 向客戶端傳送一個帶有 FIN = 1 的資料分段, 並進入 CLOSE-WAIT 狀態, 等待客戶端發來帶有 ACK = 1 的確認報文. 客戶端收到伺服器發來帶有 FIN = 1 的報文, 返回 ACK = 1 的報文確認, 為了防止伺服器端未收到需要重發, 進入 TIME-WAIT 狀態. 伺服器接收到報文後關閉連線. 客戶端等待 2MSL 後未收到回覆, 則認為伺服器成功關閉, 客戶端關閉連線.

6.apache和nginx的區別 nginx 相對 apache 的優點:

輕量級,同樣起web 服務,比apache 佔用更少的記憶體及資源 抗併發,nginx 處理請求是非同步非阻塞的,支援更多的併發連線,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高效能 配置簡潔 高度模組化的設計,編寫模組相對簡單 社群活躍 apache 相對nginx 的優點:

rewrite ,比nginx 的rewrite 強大 模組超多,基本想到的都可以找到 少bug ,nginx 的bug 相對較多 超穩定

7.SOAP SOAP(原為Simple Object Access Protocol的首字母縮寫,即簡單物件訪問協議)是交換資料的一種協議規範,使用在計算機網路Web服務(web service)中,交換帶結構資訊。SOAP為了簡化網頁伺服器(Web Server)從XML資料庫中提取資料時,節省去格式化頁面時間,以及不同應用程式之間按照HTTP通訊協議,遵從XML格式執行資料互換,使其抽象於語言實現、平臺和硬體。

8.RPC RPC(Remote Procedure Call Protocol)——遠端過程呼叫協議,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,為通訊程式之間攜帶資訊資料。在OSI網路通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網路分散式多程式在內的應用程式更加容易。

總結:服務提供的兩大流派.傳統意義以方法呼叫為導向通稱RPC。為了企業SOA,若干廠商聯合推出webservice,制定了wsdl介面定義,傳輸soap.當網際網路時代,臃腫SOA被簡化為http+xml/json.但是簡化出現各種混亂。以資源為導向,任何操作無非是對資源的增刪改查,於是統一的REST出現了.

進化的順序: RPC -> SOAP -> RESTful

9.CGI和WSGI CGI是通用閘道器介面,是連線web伺服器和應用程式的介面,使用者通過CGI來獲取動態資料或檔案等。 CGI程式是一個獨立的程式,它可以用幾乎所有語言來寫,包括perl,c,lua,python等等。

WSGI, Web Server Gateway Interface,是Python應用程式或框架和Web伺服器之間的一種介面,WSGI的其中一個目的就是讓使用者可以用統一的語言(Python)編寫前後端。

官方說明:PEP-3333

10.中間人攻擊 在GFW裡屢見不鮮的,呵呵.

中間人攻擊(Man-in-the-middle attack,通常縮寫為MITM)是指攻擊者與通訊的兩端分別建立獨立的聯絡,並交換其所收到的資料,使通訊的兩端認為他們正在通過一個私密的連線與對方直接對話,但事實上整個會話都被攻擊者完全控制。

11.c10k問題 所謂c10k問題,指的是伺服器同時支援成千上萬個客戶端的問題,也就是concurrent 10 000 connection(這也是c10k這個名字的由來)。

C10K問題的本質上是作業系統的問題。對於Web 1.0/2.0時代的作業系統,傳統的同步阻塞I/O模型處理方式都是requests per second。當建立的程序或執行緒多了,資料拷貝頻繁(快取I/O、核心將資料拷貝到使用者程序空間、阻塞,程序/執行緒上下文切換消耗大, 導致作業系統崩潰,這就是C10K問題的本質。

可見, 解決C10K問題的關鍵就是儘可能減少這些CPU資源消耗。解決方法可以使用I/O多路複用。