面試題--基礎

面試狀況

熱點考題

1.什麼是反向代理?

# web 服務器中,部署的方式大體相似,主要就是使用Nginx 實現分流,轉發,負載均衡,以及分擔服務器的壓力。Nginx部署簡單,內存消耗少,成本低。Nginx既能夠作正向代理,也能夠作反向代理

#正向代理:請求通過代理服務器從局域網發出,而後到達互聯網上的服務器
 特色:服務端不知道真正的客戶端是誰
 做用:1.訪問原本沒法訪問的服務器
      2.加速訪問服務器
      3.cache做用(正向/反向都是用緩存技術):若是用戶A訪問服務器B上的某數據J以前,已經有人經過代理服務器獲得數據J,那麼代理服務器就會把數據保存一段時間,這是代理服務器就會把緩存的數據直接發送給用戶A,專業術語(cache命中)
# 反向代理:請求從互聯網出發,先進入代理服務器,在轉發給局域網內的服務器
 特色:客戶端並不知道真正的服務端是誰
 做用:1.保護和隱藏原始資源服務器:(如圖2.1)用戶A始終認爲他訪問的是原始服務器B而不是代理服務器Z,但實際上反向代理服務器接收用戶A的應答,從原始資源服務器B中取得用戶A的需求資源,而後發送給用戶A,因爲防火牆的做用,只容許代理服務器A訪問原始資源服務器B,儘管這個虛擬環境下,防火牆和反向代理的共同做用保護了原始資源服務器B,可是用戶A不知道
      2.負載均衡:(如圖2.2)當反向代理服務器不知一個的時候,咱們甚至能夠把他們作成集羣,讓不一樣的代理服務器Z去應答不一樣的用戶,而後發送不一樣用戶須要的資源
固然反向代理服務器像正向代理服務器同樣擁有CACHE的做用,它能夠緩存原始資源服務器B的資源,而不是每次都要向原始資源服務器B請求數據,特別是一些靜態的數據,好比圖片和文件,若是這些反向代理服務器可以作到和用戶X來自同一個網絡,那麼用戶X訪問反向代理服務器X,就會獲得很高質量的速度。(CDN的核心技術就是用反向代理)
反向代理的結論:與正向代理正好相反,對於客戶端而言它就是原始服務器,而且任何特別的設置。客戶端向反向代理的命名空間發送普通請求,接着反向代理將判斷向原始服務器轉交請求,並將獲取的內容返回給客戶端,就像這些內容原本就是它本身的

基本上,網上作正反向代理的程序不少,能作正向代理的軟件大部分也能夠作反向代理。開源軟件中最流行的就是squid,既能夠作正向代理,也有不少人用來作反向代理的前端服務器。另外MS ISA也能夠用來在WINDOWS平臺下作正向代理。反向代理中最主要的實踐就是WEB服務,近些年來最火的就是Nginx了。網上有人說NGINX不能作正向代理,實際上是不對的。NGINX也能夠作正向代理,不過用的人比較少了。
#區別:正向代理的對象是客戶端,反向代理的對象是服務端

# 透明代理:客戶端根本不須要知道有代理服務器的存在,它改編了你的request fields(報文),並會傳送真實IP,加密的透明代理是屬於匿名代理,意思是不用設置代理了實踐的例子:不少公司使用行爲管理軟件

用戶A和用戶B並不知道行爲管理設備充當透明代理行爲,當用戶A或用戶B向服務器A或服務器B提交請求的時候,透明代理設備根據自身策略攔截並修改用戶A或B的報文,並做爲實際的請求方,向服務器A或B發送請求,當接收信息回傳,透明代理再根據自身的設置把容許的報文發回至用戶A或B,如圖(3.1),若是透明代理設置不容許訪問服務器B,那麼用戶A或者用戶B就不會獲得服務器B的數據。

1560903041403

1560903128640

1560930957167

1560931452738

1560934310076

2.談談你對多進程,多線程,以及協程的理解,項目是否用?

#進程:一個運行的程序(代碼)就是一個進程,沒有運行的代碼叫作程序,進程是系統資源分配的最小單位,進程擁有本身獨立的內存空間,因此進程間數據不共享,開銷大
# 多進程的使用使用場景:適合在CPU密集型操做(CPU操做指令比較多,好比:浮點運算)
進程:並行(同一時刻多個任務同時運行)
實現並行的庫:mulitprocessing

#線程:調度執行的最小單位,也叫執行路徑,不能獨立存在,依賴進程存在,一個進程至少有一個線程,多核線程共享內存(數據共享,共享全局變量),從而極大的提升了程序的運行效率
# 多線程的使用場景:適合在IO密集型操做(讀寫數據操做比較多的,好比爬蟲)
線程:併發(在同一時間段內多個任務都在運行,可是不會在同一時刻同時運行,存在交替執行的狀況)
實現併發的庫:threading

#協程:是一種用戶態的輕量級線程,協程的調度徹底由用戶控制,協程擁有本身的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,恢復先前保存的寄存器上下問和棧,直接操做棧則基本沒有內核切換的開銷,能夠不加鎖的訪問全局變量,因此上下文的切換很是快

3.什麼是多線程競爭?

線程是非獨立的,同一個進程裏面線程是數據共享的,當各個線程訪問數據資源時,會出現競爭狀態時,數據幾乎同步會被多個線程佔用,形成數據混亂,形成線程不安全,就是多線程競爭

鎖和GIL

# 怎麼解決多線程競爭問題?--鎖
# 鎖的好處:確保了某段關鍵代碼(共享數據資源)只能由一個線程從頭至尾完整地執行,能夠解決多線程資源競爭下的原子操做問題
#鎖的壞處:組織了多線程併發執行,包含鎖的偶段代碼實際只能以單線程模式執行,效率就大大地降低了
鎖的致命問題:死鎖
解釋一下什麼是鎖?
#鎖(Lock):Python提供的對線程控制的對象。有互斥鎖,死鎖,可重入鎖
死鎖:若是若干個子線程在系統資源競爭時,都在等待對方某部分資源接觸佔用狀態,結果是都不肯意先解鎖,程序就沒法執行下去,這就是死鎖(程序並無掛掉)
GIL鎖:全局解釋器鎖(只有在Cpython中裏面有)
做用:限制多線程同時執行,保證同一時間只有一個線程執行,因此Cpython裏面的多線程實際上是僞多線程,因此python裏面經常用協程技術來代替多線程,

#進程和線程的切換由系統決定的,而協程是由哦咱們本身決定的,而模塊gevent下切換是遇到耗時操做纔會切換到
三者的關係:進程裏面有線程,線程裏面有協程

4.什麼是線程安全,什麼是互斥鎖?

每一個對象對應於一個可稱爲「互斥鎖」的標記,這個標記用來包保證在任一時刻只能由一個線程訪問該對象

同一個進程中的多線程之間是共享系統資源的,多個線程同時對一個對象進行操做,一個線程操做還沒有結束,另外一個已經對其進行操做,致使最終結果出現錯誤,慈此時須要對被操做對象添加互斥u哦,保證每一個線程對該對象的操做都獲得正確的結果

5.cpu,內存,硬盤之間的關係,例如在硬盤中有一個文件,裏面只有兩個數字1,若是要在頁面上顯示這個文件中的兩個數相加,具體的流程是如何實現的

內存:計算機內存儲器,
硬盤是屬於計算機外存儲器,
CPU一般只和內存交換戶據,斷電後數據會丟失
硬盤首先讀取這個文件,將數字發送到內存中,內存將數據發送到CPU中進行數據處理,處理完成後發送到內存,再發送到硬盤中展現

6.打開瀏覽器輸入www.baidu.com,回車到頁面展現百度頁面的過程一共發生了什麼

# 1. 在瀏覽器中輸入URL
URL: 統一資源定位符,用於定位互聯網的資源,主要包括:協議,網絡地址,資源路徑
# 2. 域名解析
瀏覽器不知道baidu.com是什麼東西,須要查找百度所在服務器的IP地址,才能找到目標

#爲何咱們要使用域名而不是直接訪問IP地址?(很簡單:很差記)

域名解析的流程:
    瀏覽器緩存--瀏覽器有百度DNS則會緩存DNS,若沒有轉至下面
    系統緩存--從Host文件中查找對應的百度域名和IP,若沒有轉至下面
    路由器緩存--通常路由器也會緩存域名信息
    ISP DNS緩存 -- 例如到電信的DNS上查找緩存,若是沒有找到則會向 根域名服務器查找域名對應IP
    
# 3. 在本地dns服務器向頂級域.com發起請求,頂級域接收到請求,告訴本地dns服務器域名的解釋服務器的地址,並非告訴本地服務器域名和IP地址的對應關係
# 4. 本地dns服務器向域名的解析服務器發出請求,這時就能收到一個域名和IP地址對應關係,本地DNS服務器不只要把IP地址返回給用戶電腦,還要把這個對應關係保存在緩存中,以備下次別的用戶查詢時,能夠直接返回結果,加快網絡訪問。
# 5. IP地址返回給本地服務器處理請求,服務器通常都會安裝一個用於接收處理請求的應用—web server常見的web server產品有apache、nginx等而且決定採用哪一種方式來處理這個請求,讀取請求,而後造成html響應。
# 6. 客戶端瀏覽器開始處理,解析渲染頁面可視化

7.數據庫的外鏈接和內鏈接

返回的結果集選取了兩個表中全部相匹配的數據,捨棄了不匹配的數據。因爲內鏈接是從結果表中刪除與其餘鏈接表中沒有匹配的全部行,因此內鏈接可能會形成信息的丟失。內鏈接語法以下:
select fieldlist from table1 [inner] join table2 on table1.column = table2.column

外鏈接不只包含符合鏈接條件的行,還包含左表(左鏈接時)、右表(右鏈接時)或兩個邊接表(全外鏈接)中的全部數據行。SQL外鏈接共有三種類型:左外鏈接(關鍵字爲LEFT OUTER JOIN)、右外鏈接(關鍵字爲RIGHT OUTER JOIN)和全外鏈接(關鍵字爲FULL OUTER JOIN)。外鏈接的用法和內鏈接同樣,只是將INNER JOIN關鍵字替換爲相應的外鏈接關鍵字便可。
內鏈接只顯示符合鏈接條件的記錄,外鏈接除了顯示符合條件的記錄外,還顯示錶中的記錄,例如,若是使用左外鏈接,還顯示左表中的記錄。
SELECT XXX FROM XXX LEFT [OUTER] JOIN XXX ON XXX

8.redis經常使用的數據類型

1561033558004

在具體描述這幾種數據類型以前,咱們先經過一張圖瞭解下Redis內部內存管理中是如何描述這些不一樣數據類型的:

         首先Redis內部使用一個redisObject對象來表示全部的key和value,redisObject最主要的信息如上圖所示:
         type表明一個value對象具體是何種數據類型,

         encoding是不一樣數據類型在redis內部的存儲方式,

         好比:type=string表明value存儲的是一個普通字符串,那麼對應的encoding能夠是raw或者是int,若是是int則表明實際redis內部是按數值型類存儲和表示這個字符串的,固然前提是這個字符串自己能夠用數值表示,好比:"123" "456"這樣的字符串。
       這裏須要特殊說明一下vm字段,只有打開了Redis的虛擬內存功能,此字段纔會真正的分配內存,該功能默認是關閉狀態的,該功能會在後面具體描述。經過上圖咱們能夠發現Redis使用redisObject來表示全部的key/value數據是比較浪費內存的,固然這些內存管理成本的付出主要也是爲了給Redis不一樣數據類型提供一個統一的管理接口
    
    
#String
#Hash
#List
#Set
#Sorted set
#pub/sub
#Transactions

9.什麼是RestFul?

#REST: 是一種架構風格,一種Web Service能夠知足REST的幾個條件,一般就成這個系統是Resrful的
#條件:C/S架構,無狀態,能夠cache,分層
# REST的三要素:
1.惟一的天然標識
2.簡單的方法
3.必定的表達方式
REST 是以 資源 爲中心, 名詞即資源的地址, 動詞即施加於名詞上的一些有限操做, 表達是對各類資源形態的抽象.
以HTTP爲例, 名詞即爲URI(統一資源標識), 動詞包括POST, GET, PUT, DELETE等(還有其它不經常使用的2個,因此 整個動詞集合是有限的), 資源的形態(如text, html, image, pdf等)

RPC與REST的區別
RPC:通常採用TCP通訊協議,性能高,靈活性低
    以動詞爲中心的(就是一些方法:get、post)
    當你要須要加入新功能時,你必需要添加更多的動詞, 這時候服務器端須要實現 相應的動詞(方法), 客戶端須要知道這個新的動詞並進行調用.
REST:通常採用HTTP通訊協議,性能相對較低,靈活性高
    以名詞爲中心(一些資源的地址:URL)
    假使我請求的是 hostname/index/, 不管這個URI對應的服務怎麼變化,客戶端是無需 關注和更新的,而這種變化對客戶端也是透明的.
    
至於其它的區別,如對實現語言的依賴, 耦合性等,這些都是上面提到的這個根本區別所衍生的.
    
    當你天天使用HTTP衝浪時,你都在使用 REST 與遠程的服務器進行親密接觸. 當你使用Gtalk和同事朋友溝通時,你則是在享受着 RPC 的便利.

10.HTTP/HTTPS

HTTPS和HTTP的區別主要以下:
1.HTTPS須要ca申請證書,通常免費證書較少,所以須要必定費用
2.HTTP是超文本傳輸協議,信息是銘文傳輸,HTTPS則是具備安全性的ssl加密傳輸協議
3.HTTP和HTTPS使用的是徹底不一樣的連接方式,用的端口不同,前者是80 後者是443
4.http的連接很簡單是無狀態的,HTTPS協議是SSL+http協議構建的能夠進行加密傳輸,身份認證的網絡協議,比http安全

HTTP屬於TCP/IP模型中的運用層協議,因此通訊的過程實際上是對應數據的入棧和出棧。 
1、HTTP和HTTPS的基本概念
HTTP:是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它可使瀏覽器更加高效,使網絡傳輸減小。
HTTPS:是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。
HTTPS協議的主要做用:1.創建一個信息安全通道,來保證數據傳輸的安全;2.確認網站的真實性

HTTP特色:1.支持客戶/服務器模式(C/S)
         2.簡單快速:客戶端請求服務時,只須要發送請求方法和路徑,請求方法有GET/POST/HEAD,每種防範規定了客戶與服務器練習的類型不一樣,因爲HTTP協議簡單,使得http服務器的程序規模小,通訊速度快
         3.靈活:http容許傳輸任意類型的數據對象
         4.無鏈接:含義是顯示每次連接只能處理一個請求,服務器處理完客戶端的請求,並接受到客戶的應答後,即斷開連接,節省傳輸時間
         5.無狀態:http協議就是無狀態協議,無狀態是指協議對於事物處理沒有記憶功能,缺乏狀態意味着若是後續處理須要前面的信息,則它必須重傳,這樣可能致使每次鏈接傳送的數據量增大。另外一方面,在服務器不須要先前信息時它的應答就較快
 
HTTP工做流程:
    第一步:創建TCP/IP鏈接,客戶端與服務器經過Socket三次握手進行鏈接

    第二步:客戶端向服務端發起HTTP請求(例如:POST/login.html http/1.1)

    第三步:客戶端發送請求頭信息,請求內容,最後會發送一空白行,標示客戶端請求完畢

    第四步:服務器作出應答,表示對於客戶端請求的應答,例如:HTTP/1.1 200 OK

    第五步:服務器向客戶端發送應答頭信息

    第六步:服務器向客戶端發送請求頭信息後,也會發送一空白行,標示應答頭信息發送完畢,接着就以Content-type要求的數據格式發送數據給客戶端

    第七步:服務端關閉TCP鏈接,若是服務器或者客戶端增Connection:keep-alive就表示客戶端與服務器端繼續保存鏈接,在下次請求時能夠繼續使用此次的鏈接
        
HTTPS的特色:HTTPS是HTTP協議的修改,它加密數據並確保其機密性。其配置可保護用戶在與網站交互時免於竊取我的信息和計費數據。
優勢:提供優質的保密的信息,保證了用戶戶據的安全性,同時必定成度上保護了服務端,使用惡意攻擊和假裝數據的成本大大提升
缺點:1.https的技術門檻高
    2. 大多數網站並不關心數據的安全性和保密性
    3. https加劇了服務器的復古但
    4.http網站任然大鬼哦沒的使用
    
HTTPS的工做流程
第一步:客戶使用https的URL訪問Web服務器,要求與Web服務器創建SSL鏈接。

第二步:Web服務器收到客戶端請求後,會將網站的證書信息(證書中包含公鑰)傳送一份給客戶端。

第三步:客戶端的瀏覽器與Web服務器開始協商SSL鏈接的安全等級,也就是信息加密的等級。

第四步:客戶端的瀏覽器根據雙方贊成的安全等級,創建會話密鑰,而後利用網站的公鑰將會話密鑰加密,並傳送給網站。

第五步:Web服務器利用本身的私鑰解密出會話密鑰。

第六步:Web服務器利用會話密鑰加密與客戶端之間的通訊。

一下爲http通過的幾層模型前端

1561036953556

11.docker 建立鏡像

 

12.隊列,鏈表

棧##
棧是一種動態集合,它是一種LIFO(last in first out後進先出)結構
棧的實現:
(1)數組
(2)鏈表
棧要記錄的數據:
(1)棧頂位置top
注意這個top有兩種理解方式,一種是表示棧的最後一個數據的位置,另外一種是表示棧的最後一個數據的下一個位置,這兩種理解對棧的操做代碼有必定的影響
(2)棧最大大小size
棧的操做:
(1)STACK_EMPTY():判斷棧是否爲空
(2)PUSH(X):向棧中添加一個值,注意棧是否爲滿的
(3)POP():從棧中彈出一個值,注意棧是否爲空

棧的簡要實現:github棧
棧的應用:
(1)括號匹配問題
隊列##
與棧不一樣,它是一種FIFO(first in first out先進先出)結構
隊列的實現:
(1)數組
(2)鏈表
隊列要記錄的數據:
(1)隊首位置head:第一個元素位置
(2)隊尾位置tail:下一個元素要插入的位置(最後一個元素的下一個位置)
(3)隊列最大大小size
隊列的操做:
(1)ENQUEUE(x):入隊
(2)DEQUEUE():出隊
(3)EMPTY():隊列爲空,head=tail
(4)FULL():隊列爲滿,head=(tail+1)%size

隊列的簡要實現:github隊列
隊列的應用:
(1)
鏈表##
與數組中元素地址連續不一樣,鏈表中兩個元素地址不必定連續,而是由專門的一個指針指明該元素的後一個(前一個)元素的地址。
鏈表種類:
(1)單向鏈表:只有指向後一個元素的指針
(2)雙向鏈表:有指向後一個和前一個元素的指針
(3)循環鏈表:鏈表內存在一個環
鏈表節點(Node)記錄的數據:
(1)要存儲的數據data
(2)下一個節點地址Node* next
(3)如果雙向鏈表還要存儲前一個節點地址Node prev
鏈表(LinkedList)記錄的數據:
(1)鏈表的頭指針Node head
(2)可能還記錄鏈表的尾指針 Node* tail
鏈表的操做:
(1)SEARCH(x):鏈表的搜索
(2)INSERT(i,x):鏈表的插入,在第i個位置插入x
(3)DELETE(x):鏈表的刪除
哨兵(sentinel):
爲了減小邊界條件的判斷(是否爲空鏈表等等),引入哨兵,使得鏈表永遠不爲「空」。
指針和對象的實現:
有些語言好比Java沒有指針(C中就存在指針),這時咱們須要考慮指針的替代實現方式。
(1)用二維數組表示指針
咱們能夠設置一個n*3的數組記錄n個節點,那個3就表示存儲的數據、前一個元素的座標(index)和後一個元素的座標。
(2)用一維數組表示指針

樹##
樹的種類:
(1)二叉樹
二叉樹要存儲4個數據,分別是節點攜帶的信息和其父節點、左右子節點的指針。
(2)分支無限制的有根樹:
上面二叉樹每一個節點最多有兩個子節點,而分支無限制的有根數則沒有這個限制,可能有3個、5個甚至更多子節點。因此存儲這種數據結構的問題在於咱們事先並不知道應該設置多少個child指針,若設置的少了不能知足要求,設置的過多又會浪費空間。因此這裏提出一種新的描述這種數據結構的方法——左孩子右兄弟表示法,這種方法每一個節點設置3個指針:父指針、從左數第一個孩子的指針、其右側相鄰的兄弟指針,以下圖所示

堆##
堆其實是以數組形式存儲的二叉樹
堆須要存儲的數據:
(1)數組的大小max-size
(2)堆元素個數size,這裏size要小於max-size
堆中元素經過座標來肯定父節點、左右子節點,具體來講:
一個節點i的父節點:[i/2]
一個節點i的左子節點:[i2]
一個節點i的右子節點:[i2+1]
堆的分類:
(1)最大堆
知足全部節點都比其父節點值小(小於等於)的堆
A[i/2]>=A[i]
(2)最小堆
知足全部節點都比其父節點值大(大於等於)的堆
A[i/2]<=A[i]
堆的操做:
(1)維護堆的性質(HEAPIFY)
這裏指維護最大堆或最小堆的性質。假設一個數組中下標爲i的節點的子節點知足最大(小)堆性質,但自身不必定知足這個性質,這時就須要HEAPIFY,具體來講是要比較這個節點和其兩個子節點的大小,將其中的大(小)的和該節點位置交換,這樣這個節點及其兩個子節點就知足最大(小)堆的性質了,可是可能交換後子節點不知足堆的性質,因此這裏要遞歸調用HEAPIFY,直到達到最下層節點,這樣就維護了堆的性質。HEAPIFY耗時O(lgn)
(2)建堆(BUILD-HEAPIFY)
從中間那個元素開始到第一個元素,逐一調用HEAPIFY函數,便可完成建堆。
逐一從中間那個元素開始遞減而不是從第一個元素遞增,這時爲了保證每次調用HEAPIFY都能保證該節點的子節點都知足最大(小)堆的性質,不然沒法調用HEAPIFY。中間那個元素是第一個可能不知足最大(小)堆性質的節點,因此從這裏開始維護(HEAPIFY)。一個建堆的例子以下所示:[5,3,17,10,84,19,6,22,9]


建堆

建堆的指望時間爲O(n)

堆的應用:
(1)堆排序(詳見排序算法)
(2)優先隊列

1561335196938

## python中實現雙鏈表,棧,隊列
1.雙鏈表

class Node(object):
    def __init__(self, value=None):
        self._prev = None
        self.data = value
        self._next = None
        
    def __str__(self):
        return "Node(%s)" %s self.data
    
class DoubleLinkedlist(object):
    def __init__(self):
        self._head = None()
        
    def insert(self, value):
        element = Node(value)
        element._next = self._head
        self._head._prev = element
        self._head = element
        

    def search(self, value):
        if not self._head._next:
            raise ValueError("the linked list is empty")
        temp = self._head
        while temp.data != value:
            temp = temp._next
        return temp

    def delete(self, value):
        element = self.search(value)
        if not element:
            raise ValueError('delete error: the value not found')
        element._prev._next = element._next
        element._next._prev = element._prev
        return element.data

    def __str__(self):
        values = []
        temp = self._head
        while temp and temp.data:
            values.append(temp.data)
            temp = temp._next
        return "DoubleLinkedList(%s)"%values

    
2.棧
class Stack(object):
    def __init__(self):
        self._top = 0
        self._stack = []

    def put(self, data):
        self._stack.insert(self._top, data)
        self._top += 1

    def pop(self):
        if self.isEmpty():
            raise ValueError('stack 爲空')
        self._top -= 1
        data = self._stack[self._top]

        return data

    def isEmpty(self):
        if self._top == 0:
            return True
        else:
            return False

    def __str__(self):
        return "Stack(%s)"%self._stack

3.隊列

class Queue(object):
    def __init__(self, max_size=float('inf')):
        self._max_size = max_size
        self._top = 0
        self._tail = 0
        self._queue = []

    def put(self, value):
        if self.isFull():
            raise ValueError("the queue is full")
        self._queue.insert(self._tail, value)
        self._tail += 1

    def pop(self):
        if self.isEmpty():
            raise ValueError("the queue is empty")
        data = self._queue.pop(self._top)
        self._top += 1
        return data

    def isEmpty(self):
        if self._top == self._tail:
            return True
        else:
            return False

    def isFull(self):
        if self._tail == self._max_size:
            return True
        else:
            return False

    def __str__(self):
        return "Queue(%s)"%self._queue

13. 什麼是Ajax?

Ajax = 異步 JavaScript 和XML。
Ajax是一種用於建立快速動態網頁的技術。
經過在後臺與服務器進行少許數據交換,Ajax可使網頁實現異步更新。這意味着能夠在不從新加載整個網頁的狀況下,對網頁的某部分進行更新。
傳統的網頁(不使用 Ajax)若是須要更新內容,必需重載整個網頁面。

發送請求的四個步驟:
(1)初始化XMLHTTPRequest對象。
(2)爲XMLHTTPRequest對象指定一個回調函數,用於對返回結果進行處理。
(3)建立一個與服務器的鏈接。
(4)向服務器發送請求。

14.什麼是虛擬機?

經過軟件模擬具備灣鎮反硬件系統功能的,運行在一個徹底隔離環境中的完整的計算機系統

權重java

1561436035877

mongdo 使用內存上限python

python基礎

一.基礎語法

1.2 a=1,b=2,不用中間變量交換a 和b 的值?(2018-3-29-lxy)
方法一:
1. a = a+b
2. b = a-b
3. a = a-b
方法二:
1. a = a^b
2. b =b^a
3. a = a^b
方法三:
1. a,b = b,a
print 方法默認調用sys.stdout.write 方法,即往控制檯打印字符串。
1.4 下面這段代碼的輸出結果將是什麼?請解釋?(2018-3-30-lxy)
1. class Parent(object):
2.      x = 1
3. class Child1(Parent):
4.      pass
5. class Child2(Parent):
6.      pass
7. print Parent.x, Child1.x, Child2.x
8. Child1.x = 2
9. print parent.x, Child1.x, Child2.x
10. parent.x = 3
11. print Parent.x, Child1.x, Child2.x


結果爲:
1 1 1 #繼承自父類的類屬性x,因此都同樣,指向同一塊內存地址。
1 2 1 #更改Child1,Child1 的x 指向了新的內存地址。
3 2 3 #更改Parent,Parent 的x 指向了新的內存地址。
1.5 簡述你對input()函數的理解?
在Python3 中,input()獲取用戶輸入,不論用戶輸入的是什麼,獲取到的都是字符串類型的。
在Python2 中有raw_input()和input(), raw_input()和Python3 中的input()做用是同樣的,
input()輸入的是什麼數據類型的,獲取到的就是什麼數據類型的。
2.1 閱讀下面的代碼,寫出A0,A1 至An 的最終值。(2018-3-30-lxy)
1. A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))
2. A1 = range(10)
3. A2 = [i for i in A1 if i in A0]
4. A3 = [A0[s] for s in A0]
5. A4 = [i for i in A1 if i in A3]
6. A5 = {i:i*i for i in A1}
7. A6 = [[i,i*i] for i in A1]\

............

結果是:
1. A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
2. A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3. A2 = []
4. A3 = [1, 3, 2, 5, 4]
1. A4 = [1, 2, 3, 4, 5]
2. A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
3. A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36],[7, 49],[8, 64], [9,81]]
2.2 range 和xrange 的區別?(2018-3-30-lxy)

目前再python3版本種xrange已經被取消mysql

二者用法相同,不一樣的是range 返回的結果是一個列表,而xrange 的結果是一個生成器,前者是直接開闢一塊內存空間來保存列表,後者是邊循環邊使用,只有使用時纔會開闢內存空間,因此當列表很長時,使用xrange 性能要比range 好。linux

1. l = []
2. for i in xrange(10):
3. l.append({‘num’:i})
4. print l
############

1. l = []
2. a = {‘num’:0}
3. for i in xrange(10):
4. a[‘num’] = i
5. l.append(a)
6. print l

以上兩段代碼的運行結果是否相同,若是不相同,緣由是什麼?
上方代碼的結果:
1. [{‘num’:0},{‘num’:1},{‘num’:2},{‘num’:3},{‘num’:4},{‘num’:5},{‘num’:6},{‘num’:7},{‘num’:8},
{‘num’:9}]
下方代碼結果:
1. [{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},{‘num’:9},
{‘num’:9}]

緣由是:字典是可變對象,在下方的l.append(a)的操做中是把字典a 的引用傳到列表l 中,當後
續操做修改a[‘num’]的值的時候,l 中的值也會跟着改變,至關於淺拷貝。
3.1 4G 內存怎麼讀取一個5G 的數據?(2018-3-30-lxy)
方法一:
能夠經過生成器,分屢次讀取,每次讀取數量相對少的數據(好比500MB)進行處理,處理結束後
在讀取後面的500MB 的數據。
方法二:
能夠經過linux 命令split 切割成小文件,而後再對數據進行處理,此方法效率比較高。能夠按照行
數切割,能夠按照文件大小切割。
3.2 如今考慮有一個jsonline 格式的文件file.txt 大小約爲10K,以前處理文件的代碼以下所示:(2018-3-30-lxy)
1. def get_lines():
2.      l = []
3.      with open(‘file.txt’,‘rb’) as f:
4.          for eachline in f:
5.              l.append(eachline)
6.      return l
7. if __name__ == ‘__main__’:
8.      for e in get_lines():
9.          process(e) #處理每一行數據

如今要處理一個大小爲10G 的文件,可是內存只有4G,若是在只修改get_lines 函數而其餘代碼保持不變的狀況下,應該如何實現?須要考慮的問題都有哪些?
1. def get_lines():
2.      l = []
3.      with open(‘file.txt’,’rb’) as f:
4.          data = f.readlines(60000)
5.      l.append(data)
6.      yield l

要考慮到的問題有:
內存只有4G 沒法一次性讀入10G 的文件,須要分批讀入。分批讀入數據要記錄每次讀入數據的位置。分批每次讀入數據的大小,過小就會在讀取操做上花費過多時間。
3.3 read、readline 和readlines 的區別? (2018-4-16-lxy)

read:讀取整個文件。
readline:讀取下一行,使用生成器方法。
readlines:讀取整個文件到一個迭代器以供咱們遍歷。nginx

4.2 介紹一下except 的做用和用法?(2018-4-16-lxy)

except: #捕獲全部異常
except: <異常名> : #捕獲指定異常
except:<異常名1, 異常名2> : 捕獲異常1 或者異常2
except: <異常名> , <數據> :捕獲指定異常及其附加的數據
except:<異常名1,異常名2>: <數據> :捕獲異常名1 或者異常名2,及附加的數據 git

5.1 經常使用的Python 標準庫都有哪些?(2018-3-30-lxy)

os 操做系統,time 時間,random 隨機,pymysql 鏈接數據庫,threading 線程,multiprocessing進程,queue 隊列。
第三方庫:django 和flask 也是第三方庫,requests,virtualenv, selenium,scrapy,xadmin,celery,re,hashlib,md5。
經常使用的科學計算庫(如Numpy,Scipy,Pandas)。程序員

5.2 賦值、淺拷貝和深拷貝的區別?(2018-3-30-lxy)

1、賦值
在Python 中,對象的賦值就是簡單的對象引用,這點和C++不一樣,以下所示:github

16.a = [1,2,"hello",['python', 'C++']]
17.b = a

在上述狀況下,a 和b 是同樣的,他們指向同一片內存,b 不過是a 的別名,是引用。咱們可使用b is a 去判斷,返回True,代表他們地址相同,內容相同,也可使用id()函數來查看兩個列表的地址是否相同。
賦值操做(包括對象做爲參數、返回值)不會開闢新的內存空間,它只是複製了對象的引用。也就是說除了b 這個名字以外,沒有其餘的內存開銷。修改了a,也就影響了b,同理,修改了b,也就影響了a。

2、淺拷貝(shallow copy)

淺拷貝會建立新對象,其內容非原對象自己的引用,而是原對象內第一層對象的引用。
淺拷貝有三種形式:切片操做、工廠函數、copy 模塊中的copy 函數。
好比上述的列表a;
    切片操做:b = a[:] 或者b = [x for x in a];
    工廠函數:b = list(a);
    copy 函數:b = copy.copy(a);
    
一、b = a.copy(): 淺拷貝, a 和 b 是一個獨立的對象,但他們的子對象仍是指向統一對象(是引用)。

1561364929082

3、深拷貝(deep copy)

深拷貝只有一種形式,copy 模塊中的deepcopy()函數。
深拷貝和淺拷貝對應,深拷貝拷貝了對象的全部元素,包括多層嵌套的元素。所以,它的時間和空間開銷要高。
二、b = copy.deepcopy(a): 深度拷貝, a 和 b 徹底拷貝了父對象及其子對象,二者是徹底獨立的。

1561364993788

5.3__init__ 和__new__的區別?(2018-3-30-lxy)

init 在對象建立後,對對象進行初始化。
new 是在對象建立以前建立一個對象,並將該對象返回給init。

5.4 Python 裏面如何生成隨機數?(2018-3-30-lxy)
在Python 中用於生成隨機數的模塊是random,在使用前須要import. 以下例子能夠酌情列
舉:
random.random():生成一個0-1 之間的隨機浮點數;
random.uniform(a, b):生成[a,b]之間的浮點數;
random.randint(a, b):生成[a,b]之間的整數;
random.randrange(a, b, step):在指定的集合(a,b)中,以step爲基數隨機取一個數;
random.choice(sequence):從特定序列中隨機取一個元素,這裏的序列能夠是字符串,列表,元組等。
5.5 輸入某年某月某日,判斷這一天是這一年的第幾天?(能夠用Python 標準
庫)(2018-3-30-lxy)
1. import datetime
2. def dayofyear():
3.      year = input("請輸入年份:")
4.      month = input("請輸入月份:")
5.      day = input("請輸入天:")
6.      date1 = datetime.date(year=int(year),month=int(month),day=int(day))
7.      date2 = datetime.date(year=int(year),month=1,day=1)
8.      return (date1 - date2 + 1).days
5.6 打亂一個排好序的list 對象alist?(2018-3-30-lxy)
1. import random
2. random.shuffle(alist)
5.7 說明一下os.path 和sys.path 分別表明什麼?(2018-3-30-lxy)

os.path 主要是用於對系統路徑文件的操做。
sys.path 主要是對Python 解釋器的系統環境參數的操做(動態的改變Python 解釋器搜索路徑)。

5.8 Python 中的os 模塊常見方法?(2018-4-16-lxy)

os.remove()刪除文件
os.rename()重命名文件
os.walk()生成目錄樹下的全部文件名
os.chdir()改變目錄

os.mkdir/makedirs 建立目錄/多層目錄
os.rmdir/removedirs 刪除目錄/多層目錄
os.listdir()列出指定目錄的文件
os.getcwd()取得當前工做目錄
os.chmod()改變目錄權限
os.path.basename()去掉目錄路徑,返回文件名
os.path.dirname()去掉文件名,返回目錄路徑
os.path.join()將分離的各部分組合成一個路徑名
os.path.split()返回(dirname(),basename())元組
os.path.splitext()(返回filename,extension)元組os.path.getatime\ctime\mtime 分別返回最近訪問、建立、修改時間
os.path.getsize()返回文件大小
os.path.exists()是否存在
os.path.isabs()是否爲絕對路徑
os.path.isdir()是否爲目錄
os.path.isfile()是否爲文件

5.9 Python 的sys 模塊經常使用方法?(2018-4-16-lxy)
sys.argv 命令行參數List,第一個元素是程序自己路徑
sys.modules.keys() 返回全部已經導入的模塊列表
sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback 當前處理的異常詳細信息
sys.exit(n) 退出程序,正常退出時exit(0)
sys.hexversion 獲取Python 解釋程序的版本值,16 進制格式如:0x020403F0
sys.version 獲取Python 解釋程序的版本信息
sys.maxint 最大的Int 值
sys.maxunicode 最大的Unicode 值
sys.modules 返回系統導入的模塊字段,key 是模塊名,value 是模塊
sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH 環境變量的值
sys.platform 返回操做系統平臺名稱
sys.stdout 標準輸出
sys.stdin 標準輸入
sys.stderr 錯誤輸出
sys.exc_clear() 用來清除當前線程所出現的當前的或最近的錯誤信息
sys.exec_prefix 返回平臺獨立的python 文件安裝的位置
sys.byteorder 本地字節規則的指示器,big-endian 平臺的值是'big',little-endian 平臺的值是'little'
sys.copyright 記錄python 版權相關的東西
sys.api_version 解釋器的C 的API 版本
sys.version_info 元組則提供一個更簡單的方法來使你的程序具有Python 版本要求功能
5.10 unittest 是什麼?(2018-4-16-lxy)

在Python 中,unittest 是Python 中的單元測試框架。它擁有支持共享搭建、自動測試、在測試中暫停代碼、將不一樣測試迭代成一組,等的功能。

5.11 模塊和包是什麼?(2018-4-16-lxy)

在Python 中,模塊是搭建程序的一種方式。每個Python 代碼文件都是一個模塊,並能夠引用其餘的模塊,好比對象和屬性。
一個包含許多Python 代碼的文件夾是一個包。一個包能夠包含模塊和子文件夾。

6.1 Python 是強語言類型仍是弱語言類型?(2018-3-30-lxy)

Python 是強類型的動態腳本語言。
強類型:不容許不一樣類型相加。
動態:不使用顯示數據類型聲明,且肯定一個變量的類型是在第一次給它賦值的時候。
腳本語言:通常也是解釋型語言,運行代碼只須要一個解釋器,不須要編譯。

6.2 談一下什麼是解釋性語言,什麼是編譯性語言? (2018-3-30-lxy)

計算機不能直接理解高級語言,只能直接理解機器語言,因此必需要把高級語言翻譯成機器語言,
計算機才能執行高級語言編寫的程序。
解釋性語言在運行程序的時候纔會進行翻譯。

編譯型語言寫的程序在執行以前,須要一個專門的編譯過程,把程序編譯成機器語言(可執行文件)。

6.3 Python 中有日誌嗎?怎麼使用? (2018-3-30-lxy)
有日誌。
Python 自帶logging 模塊,調用logging.basicConfig()方法,配置須要的日誌等級和相應的參數,
Python 解釋器會按照配置的參數生成相應的日誌。
6.4 Python 是如何進行類型轉換的?(2018-3-30-lxy)
內建函數封裝了各類轉換函數,可使用目標類型關鍵字強制類型轉換,進制之間的轉換能夠用
int(‘str’,base=’n’)將特定進制的字符串轉換爲十進制,再用相應的進制轉換函數將十進制轉換
爲目標進制。
可使用內置函數直接轉換的有:
list---->tuple tuple(list)
tuple---->list list(tuple)
6.5 Python2 與Python3 的區別?(2018-3-30-lxy)

1) 核心類差別

  1. Python3 對Unicode 字符的原生支持。
    Python2 中使用ASCII 碼做爲默認編碼方式致使string 有兩種類型str 和unicode,Python3 只
    支持unicode 的string。Python2 和Python3 字節和字符對應關係爲:

1561376946130

6.10 什麼是Python 的命名空間?(2018-4-16-lxy)

在Python 中,全部的名字都存在於一個空間中,它們在該空間中存在和被操做——這就是命名空間。它就好像一個盒子,每個變量名字都對應裝着一個對象。當查詢變量的時候,會從該盒子裏面尋找相應的對象。

6.11 你所遵循的代碼規範是什麼?請舉例說明其要求?(2018-4-20-lxy)

PEP8 規範。

  1. 變量
    常量:大寫加下劃線USER_CONSTANT。
    私有變量: 小寫和一個前導下劃線_private_value。
    Python 中不存在私有變量一說,如果遇到須要保護的變量,使用小寫和一個前導下劃線。但這只是
    程序員之間的一個約定,用於警告說明這是一個私有變量,外部類不要去訪問它。但實際上,外部類還
    是能夠訪問到這個變量。
    內置變量: 小寫,兩個前導下劃線和兩個後置下劃線__class__

兩個前導下劃線會致使變量在解釋期間被改名。這是爲了不內置變量和其餘變量產生衝突。用戶定義的變量要嚴格避免這種風格。以避免致使混亂。

  1. 函數和方法
    整體而言應該使用,小寫和下劃線。但有些比較老的庫使用的是混合大小寫,即首單詞小寫,以後
    每一個單詞第一個字母大寫,其他小寫。但如今,小寫和下劃線已成爲規範。
    私有方法:小寫和一個前導下劃線
    這裏和私有變量同樣,並非真正的私有訪問權限。同時也應該注意通常函數不要使用兩個前導下
    劃線(當遇到兩個前導下劃線時,Python 的名稱改編特性將發揮做用)。
    特殊方法:小寫和兩個前導下劃線,兩個後置下劃線
    這種風格只應用於特殊函數,好比操做符重載等。
    函數參數: 小寫和下劃線,缺省值等號兩邊無空格

  2. 類老是使用駝峯格式命名,即全部單詞首字母大寫其他字母小寫。類名應該簡明,精確,並足以從
    中理解類所完成的工做。常見的一個方法是使用表示其類型或者特性的後綴,例如:
    SQLEngine,MimeTypes 對於基類而言,可使用一個Base 或者Abstract 前綴BaseCookie,
    AbstractGroup
  3. 模塊和包
    除特殊模塊__init__ 以外,模塊名稱都使用不帶下劃線的小寫字母。
    如果它們實現一個協議,那麼一般使用lib 爲後綴,例如:
    import smtplib
    import os
    import sys
  4. 關於參數
    5.1 不要用斷言來實現靜態類型檢測。斷言能夠用於檢查參數,但不該僅僅是進行靜態類型檢測。
    Python 是動態類型語言,靜態類型檢測違背了其設計思想。斷言應該用於避免函數不被毫無心義的調用。
    5.2 不要濫用*args 和**kwargs。*args 和**kwargs 參數可能會破壞函數的健壯性。它們使簽名變得模糊,並且代碼經常開始在不該該的地方構建小的參數解析器。
  5. 其餘
    6.1 使用has 或is 前綴命名布爾元素
    is_connect = True
    has_member = False
    6.2 用複數形式命名序列
    members = ['user_1', 'user_2']
    6.3 用顯式名稱命名字典
    person_address = {'user_1':'10 road WD', 'user_2' : '20 street huafu'}
    6.4 避免通用名稱
    諸如list, dict, sequence 或者element 這樣的名稱應該避免。
    6.5 避免現有名稱
    諸如os, sys 這種系統已經存在的名稱應該避免。
  6. 一些數字
    一行列數: PEP 8 規定爲79 列。根據本身的狀況,好比不要超過滿屏時編輯器的顯示列數。
    一個函數: 不要超過30 行代碼, 便可顯示在一個屏幕類,能夠不使用垂直遊標便可看到整個函數。
    一個類: 不要超過200 行代碼,不要有超過10 個方法。一個模塊不要超過500 行。
  7. 驗證腳本
    能夠安裝一個pep8 腳本用於驗證你的代碼風格是否符合PEP8。

2、數據結構

1.字典
1.6 現有字典d={‘a’:24,’g’:52,’l’:12,’k’:33}請按字典中的value
值進行排序? (2018-4-23-lxy)
sorted(d.items(),key = lambda x:x[1])
2.字符串
2.1 如何理解Python 中字符串中的\字符?(2018-3-30-lxy)

有三種不一樣的含義:
一、轉義字符二、路徑名中用來鏈接路徑名三、編寫太長代碼手動軟換行。

2.4 請按alist 中元素的age 由大到小排序(2018-3-30-lxy)

alist [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}]

def sort_by_age(list1):

​ return sorted(alist, key=lambda x:x["age"],reverse=True)

3.列表

列表.extend(Iterable):將可迭代對象中的元素追加到列表。

1.# 有兩個列表a 和b a.extend(b) 會將b 中的元素追加到列表a 中
2.In [10]: a = [11, 22, 33]
3.In [11]: b = [44, 55, 66]
4.In [12]: a.extend(b)
5.In [13]: a
6.Out[13]: [11, 22, 33, 44, 55, 66]# 有列表c 和字符串d c.extend(d) 會將字符串d 中的每一個字符拆開做爲元素插入到列表
c
7.In [14]: c = ['j', 'a', 'v', 'a']
8.In [15]: d = "python"
9.In [16]: c.extend(d)
10.In [17]: c
11.Out[17]: ['j', 'a', 'v', 'a', 'p', 'y', 't', 'h', 'o','n']

3)刪除
del 列表名[index]:刪除指定索引的數據。

1.In [25]: name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu"]# 刪除索引是1 的數據
2.In [26]: del name_list[1]
3.In [27]: name_list
4.Out[27]: ['zhangsan', 'wangwu', 'zhaoliu']

列表名.remove(數據):刪除第一個出現的指定數據。

5.In [30]: name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu", "lisi"]# 刪除第一次出現的lisi 的數據
6.In [31]: name_list.remove("lisi")
7.In [32]: name_list
8.Out[32]: ['zhangsan', 'wangwu', 'zhaoliu', 'lisi']
列表名.pop():刪除末尾的數據,返回值: 返回被刪除的元素。
9.In [33]: name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu"]# 刪除最後一個元素zhaoliu 並將元素zhaoliu 返回
10.In [34]: name_list.pop()
11.Out[34]: 'zhaoliu'
12.In [35]: name_list
13.Out[35]: ['zhangsan', 'lisi', 'wangwu']
列表名.pop(index):刪除指定索引的數據,返回被刪除的元素。
14.In [36]: name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu"]# 刪除索引爲1 的數據lisi
15.In [37]: name_list.pop(1)
16.Out[37]: 'lisi'
17.In [38]: name_list
18.Out[38]: ['zhangsan', 'wangwu', 'zhaoliu']
列表名.clear():清空整個列表的元素。
19.In [40]: name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu"]
20.In [41]: name_list.clear()
21.In [42]: name_list
22.Out[42]: []

4)排序
列表名.sort():升序排序從小到大。
23.In [43]: a = [33, 44, 22, 66, 11]
24.In [44]: a.sort()
25.In [45]: a
26.Out[45]: [11, 22, 33, 44, 66]
列表名.sort(reverse=True):降序排序從大到小。
27.In [46]: a = [33, 44, 22, 66, 11]
28.In [47]: a.sort(reverse=True)
29.In [48]: a
30.Out[48]: [66, 44, 33, 22, 11]
列表名.reverse():列表逆序、反轉。
31.In [50]: a = [11, 22, 33, 44, 55]
32.In [51]: a.reverse()
33.In [52]: a
34.Out[52]: [55, 44, 33, 22, 11]
5)統計相關
len(列表名):獲得列表的長度。
35.In [53]: a = [11, 22, 33, 44, 55]
36.In [54]: len(a)
37.Out[54]: 5
    列表名.count(數據):數據在列表中出現的次數。
38.In [56]: a = [11, 22, 11, 33, 11]
39.In [57]: a.count(11)
40.Out[57]: 3
列表名.index(數據):數據在列表中首次出現時的索引,沒有查到會報錯。
41.In [59]: a = [11, 22, 33, 44, 22]
42.In [60]: a.index(22)
43.Out[60]: 1
if 數據in 列表: 判斷列表中是否包含某元素。
44.a = [11, 22, 33, 44 ,55]
45.if 33 in a:
46. print("找到了....")
注意事項
3.1 下面代碼的輸出結果將是什麼?(2018-3-30-lxy)
1. list = ['a', 'b', 'c', 'd', 'e']
2. print list[10:]
下面的代碼將輸出[],不會產生IndexError 錯誤。就像所指望的那樣,嘗試用超出成員的個數的index來獲取某個列表的成員。
例如,嘗試獲取list[10]和以後的成員,會致使IndexError。
然而,嘗試獲取列表的切片,開始的index 超過了成員個數不會產生IndexError,而是僅僅返回一個空列表。這成爲特別讓人噁心的疑難雜症,由於運行的時候沒有錯誤產生,致使bug 很難被追蹤到。
3.2 寫一個列表生成式,產生一個公差爲11 的等差數列(2018-3-30-lxy)
1. print([x*11 for x in range(10)])
3.3 給定兩個列表,怎麼找出他們相同的元素和不一樣的元素? (2018-3-30-lxy)
1. list1 = [1,2,3]
2. list2 = [3,4,5]
3. set1 = set(list1)
4. set2 = set(list2)
5. print(set1&set2)
6. print(set1^set2)
3.4 請寫出一段Python 代碼實現刪除一個list 裏面的重複元素?(2018-3-30-lxy)
比較容易記憶的是用內置的set:
1. l1 = ['b','c','d','b','c','a','a']
2. l2 = list(set(l1))
3. print l2
若是想要保持他們原來的排序:
用list 類的sort 方法:
1. l1 = ['b','c','d','b','c','a','a']
2. l2 = list(set(l1))
3. l2.sort(key=l1.index)
4. print l2
也能夠這樣寫:
1. l1 = ['b','c','d','b','c','a','a']
2. l2 = sorted(set(l1),key=l1.index)
3. print l2
也能夠用遍歷:
1. l1 = ['b', 'c', 'd', 'b', 'c', 'a', 'a']
2. l2 = []
3. for i in l1:
4. if not i in l2:
5. l2.append(i)
6. print l2
3.8.將如下3 個函數按照執行效率高低排序(2018-4-16-lxy)
1. def f1(lIn):
2. l1 = sorted(lIn)
3. l2 = [i for i in l1 if i<0.5]
4. return [i*i for i in l2]
5.
6.
7. def f2(lIn):
8. l1 = [i for i in l1 if i<0.5]
9. l2 = sorted(l1)
10. return [i*i for i in l2]
11.
12.
13. def f3(lIn):
14. l1 = [i*i for i in lIn]
15. l2 = sorted(l1)
16. return [i for i in l1 if i<(0.5*0.5)]
按執行效率從高到低排列:f二、f1 和f3。要證實這個答案是正確的,你應該知道如何分析本身代碼的性能。Python中有一個很好的程序分析包,能夠知足這個需求。

1. import random
2. import cProfile
3. lIn = [random.random() for i in range(100000)]
4. cProfile.run('f1(lIn)')
5. cProfile.run('f2(lIn)')
6. cProfile.run('f3(lIn)')
  1. 集合
    set:set 集合,在Python 中的書寫方式的{},集合與以前列表、元組相似,能夠存儲多個數據,可是這些數據是不重複的。集合對象還支持union(聯合), intersection(交), difference(差)和sysmmetric_difference(對稱差集)等數學運算.
快速去除列表中的重複元素
  1.In [4]: a = [11,22,33,33,44,22,55]
  2.
  3.In [5]: set(a)
  4.Out[5]: {11, 22, 33, 44, 55}
  交集:共有的部分
  1.In [7]: a = {11,22,33,44,55}
  2.In [8]: b = {22,44,55,66,77}
  3.In [9]: a&b
  4.Out[9]: {22, 44, 55}
      
  並集:總共的部分
  1.In [11]: a = {11,22,33,44,55}
  2.In [12]: b = {22,44,55,66,77}
  3.In [13]: a | b
  4.Out[13]: {11, 22, 33, 44, 55, 66, 77}
  差集:另外一個集合中沒有的部分
  1.In [15]: a = {11,22,33,44,55}
  2.In [16]: b = {22,44,55,66,77}
  3.In [17]: b - a
  4.Out[17]: {66, 77}
  對稱差集(在a 或b 中,但不會同時出如今兩者中)
  1.In [19]: a = {11,22,33,44,55}
  2.In [20]: b = {22,44,55,66,77}
  3.In [21]: a ^ b
  4.Out[21]: {11, 33, 66, 77}

python綜述

Python語言和C++,java等其餘編程語言相比,他是一種解釋型腳本語言,代碼在執行時,會一行一行的解釋成CPU能理解的機器碼,同時它又是跨平臺的,能夠容許windows,linux,mac等系統上,一樣的程序邏輯,可能C語言須要1000行代碼,java有100行,可是python實現可能只須要20行,這極大程度上提高了企業的項目開發效率,
記得以前就有一篇權威報道,到2014年爲止,麻省、哈弗等頂尖高校都已經使用python做爲教學語言,如今國內的高校,也開始設置python的專業課程,如今對於企業項目後臺開發而言,不是說必定要用python開發,但如今語言自己的性能差距在實際開發的過程當中,相對於業務功能合理設計、代碼編寫架構質量等,語言底層形成的性能損失愈來愈能夠忽略不計,針對於一些特定的功能模塊,python當前也出現了pypy,JIT等大幅度提升python程序運行效率的相關技術,可以知足大多數功能的需求業務場景

具體選用python後,新項目推薦使用python3,08年python3版本發佈後,十幾年來python3生態圈第三方庫已經很是具有完備和棄權,而官方已經宣佈python2在2020年將不在維護,另外python3自己性能也和相較於python2有必定的提高

Linux基礎和git

Linux

7.1 Linux 的基本命令(怎麼區分一個文件仍是文件夾)(2018-3-30-lxy)

ls -F 在顯示名稱的時候會在文件夾後添加「/」,在文件後面加「*」。

7.2 日誌以什麼格式,存放在哪裏?(2018-3-30-lxy)

日誌以文本能夠存儲在「/var/log/」目錄下後綴名爲.log。

7.3 Linux 查看某個服務的端口? (2018-3-30-lxy)

netstat命令參數:

  -t : 指明顯示TCP端口

  -u : 指明顯示UDP端口

  -l : 僅顯示監聽套接字(所謂套接字就是使應用程序可以讀寫與收發通信協議(protocol)與資料的程序)

  -p : 顯示進程標識符和程序名稱,每個套接字/端口都屬於一個程序。

  -n : 不進行DNS輪詢,顯示IP(能夠加速操做)

便可顯示當前服務器上全部端口及進程服務,於grep結合可查看某個具體端口及服務狀況··

netstat -ntlp //查看當前全部tcp端口·

netstat -ntulp |grep 80 //查看全部80端口使用狀況·

netstat -an | grep 3306 //查看全部3306端口使用狀況·

查看一臺服務器上面哪些服務及端口

netstat -lanp

查看一個服務有幾個端口。好比要查看mysqld

ps -ef |grep mysqld

查看某一端口的鏈接數量,好比3306端口

netstat -pnt |grep :3306 |wc

查看某一端口的鏈接客戶端IP 好比3306端口

netstat -anp |grep 3306

netstat -an 查看網絡端口 lsof -i :port,使用lsof -i :port就能看見所指定端口運行的程序,同時還有當前鏈接。 nmap 端口掃描netstat -nupl  (UDP類型的端口)netstat -ntpl  (TCP類型的端口)netstat -anp 顯示系統端口使用狀況
7.4 ubuntu 系統如何設置開機自啓動一個程序? (2018-3-30-lxy)

直接修改/etc/rc0.d ~ /etc/rc6.d 和/etc/rcS.d 文件夾的內容,添加需啓動的程序,S 開頭的表示啓動,K 開頭的表示不啓動。

7.6 Linux 重定向命令有哪些?有什麼區別?(2018-4-16-lxy)

一、重定向>
Linux 容許將命令執行結果重定向到一個文件,本應顯示在終端上的內容保存到指定文件中。如:ls >test.txt ( test.txt 若是不存在,則建立,存在則覆蓋其內容)。
二、重定向>>

這個是將輸出內容追加到目標文件中。若是文件不存在,就建立文件;若是文件存在,則將新的內容追加到那個文件的末尾,該文件中的原有內容不受影響。

7.7 軟鏈接和硬連接的區別?(2018-4-16-lxy)

軟鏈接相似Windows 的快捷方式,當刪除源文件時,那麼軟連接也失效了。硬連接能夠理解爲源文件的一個別名,多個別名所表明的是同一個文件。當rm 一個文件的時候,那麼此文件的硬連接數減1,當硬連接數爲0 的時候,文件被刪除。

7.8 10 個經常使用的Linux 命令?(2018-4-20-lxy)

pwd 顯示工做路徑
ls 查看目錄中的文件

cd /home 進入'/ home' 目錄'
cd .. 返回上一級目錄
cd ../.. 返回上兩級目錄
mkdir dir1 建立一個叫作'dir1' 的目錄'
rm -f file1 刪除一個叫作'file1' 的文件',-f 參數,忽略不存在的文件,從不給出提示。
rmdir dir1 刪除一個叫作'dir1' 的目錄'
groupadd group_name 建立一個新用戶組
groupdel group_name 刪除一個用戶組
tar -cvf archive.tar file1 建立一個非壓縮的tarball
tar -cvf archive.tar file1 file2 dir1 建立一個包含了'file1', 'file2' 以及'dir1'的檔案文件
tar -tf archive.tar 顯示一個包中的內容
tar -xvf archive.tar 釋放一個包
tar -xvf archive.tar -C /tmp 將壓縮包釋放到/tmp 目錄下
tar -cvfj archive.tar.bz2 dir1 建立一個bzip2 格式的壓縮包
tar -xvfj archive.tar.bz2 解壓一個bzip2 格式的壓縮包
tar -cvfz archive.tar.gz dir1 建立一個gzip 格式的壓縮包
tar -xvfz archive.tar.gz 解壓一個gzip 格式的壓縮包
reboot 從新啓動操做系統
shutdown –r now 從新啓動操做系統,shutdown 會給別的用戶提示
shutdown -h now 馬上關機,其中now 至關於時間爲0 的狀態
shutdown -h 20:25 系統在今天的20:25 會關機
shutdown -h +10 系統再過十分鐘後自動關機
init 0 關機 init 6 重啓

git

7.10 git 合併文件有衝突,如何處理? (2018-3-30-lxy)

一、git merge 衝突了,根據提示找到衝突的文件,解決衝突若是文件有衝突,那麼會有相似的標記

二、修改完以後,執行git add 衝突文件名
三、git commit 注意:沒有-m 選項進去相似於vim 的操做界面,把conflict 相關的行刪除掉
直接push 就能夠了,由於剛剛已經執行過相關merge 操做了。

7.11 git 建立分支,合併分支
首先,建立分支dev,切換到dev分支
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b參數表示建立並切換,至關於如下兩條命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'

而後,用git branch命令查看當前分支:
$ git branch
* dev
  master
  
git branch命令會列出全部分支,當前分支前面會標一個*號。

而後,咱們就能夠在dev分支上正常提交,好比對readme.txt作個修改,加上一行:
Creating a new branch is quick.
而後提交:
$ git add readme.txt 
$ git commit -m "branch test"
[dev b17d20e] branch test
 1 file changed, 1 insertion(+)
 
如今,dev分支的工做完成,咱們就能夠切換回master分支:
$ git checkout master
Switched to branch 'master'
切換回master分支後,再查看一個readme.txt文件,剛纔添加的內容不見了!由於那個提交是在dev分支上,而master分支此刻的提交點並無變:

如今,咱們把dev分支的工做成果合併到master分支上:
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
 
 git merge命令用於合併指定分支到當前分支。合併後,再查看readme.txt的內容,就能夠看到,和dev分支的最新提交是徹底同樣的。

注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。

固然,也不是每次合併都能Fast-forward,咱們後面會講其餘方式的合併。
 合併完成後,就能夠放心地刪除dev分支了:
 $ git branch -d dev
Deleted branch dev (was b17d20e).
刪除後,查看branch,就只剩下master分支了:
$ git branch
* master


建立與合併分支
閱讀: 9909301
在版本回退裏,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來講不是指向提交,而是指向master,master纔是指向提交的,因此,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能肯定當前分支,以及當前分支的提交點:

git-br-initial

每次提交,master分支都會向前移動一步,這樣,隨着你不斷提交,master分支的線也愈來愈長。

當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

git-br-create

你看,Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!

不過,從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:

git-br-dev-fd

假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:

git-br-ff-merge

因此Git合併分支也很快!就改改指針,工做區內容也不變!

合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:

git-br-rm

真是太神奇了,你看得出來有些提交是經過分支完成的嗎?

下面開始實戰。

首先,咱們建立dev分支,而後切換到dev分支:

$ git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b參數表示建立並切換,至關於如下兩條命令:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'
而後,用git branch命令查看當前分支:

$ git branch
* dev
  master
git branch命令會列出全部分支,當前分支前面會標一個*號。

而後,咱們就能夠在dev分支上正常提交,好比對readme.txt作個修改,加上一行:

Creating a new branch is quick.
而後提交:

$ git add readme.txt 
$ git commit -m "branch test"
[dev b17d20e] branch test
 1 file changed, 1 insertion(+)
如今,dev分支的工做完成,咱們就能夠切換回master分支:

$ git checkout master
Switched to branch 'master'
切換回master分支後,再查看一個readme.txt文件,剛纔添加的內容不見了!由於那個提交是在dev分支上,而master分支此刻的提交點並無變:

git-br-on-master

如今,咱們把dev分支的工做成果合併到master分支上:

$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
git merge命令用於合併指定分支到當前分支。合併後,再查看readme.txt的內容,就能夠看到,和dev分支的最新提交是徹底同樣的。

注意到上面的Fast-forward信息,Git告訴咱們,此次合併是「快進模式」,也就是直接把master指向dev的當前提交,因此合併速度很是快。

固然,也不是每次合併都能Fast-forward,咱們後面會講其餘方式的合併。

合併完成後,就能夠放心地刪除dev分支了:

$ git branch -d dev
Deleted branch dev (was b17d20e).
刪除後,查看branch,就只剩下master分支了:

$ git branch
* master
由於建立、合併和刪除分支很是快,因此Git鼓勵你使用分支完成某個任務,合併後再刪掉分支,這和直接在master分支上工做效果是同樣的,但過程更安全。



小結
Git鼓勵大量使用分支:

查看分支:git branch

建立分支:git branch <name>

切換分支:git checkout <name>

建立+切換分支:git checkout -b <name>

合併某分支到當前分支:git merge <name>

刪除分支:git branch -d <name>
相關文章
相關標籤/搜索