0,python2和python3的區別html
""" .1 默認解釋器編碼:py2-> ascii ; py3->utf-8 .2 字符串和字節(*****) py2: unicode str = bytes py3: str,字符串 bytes,字節 .3 經典類和新式類 py2: - 經典 - 新式(直接或間接繼承object) py3: - 新式 .4 yield from ... """
20、python2和python3區別?列舉5個java
一、Python3 使用 print 必需要以小括號包裹打印內容,好比 print('hi')python
Python2 既可使用帶小括號的方式,也可使用一個空格來分隔打印內容,好比 print 'hi'mysql
二、python2 range(1,10)返回列表,python3中返回迭代器,節約內存4 linux
四、python2中unicode表示字符串序列,str表示字節序列web
python3中str表示字符串序列,byte表示字節序列ajax
五、python2中爲正常顯示中文,引入coding聲明,python3中不須要算法
六、python2中是raw_input()函數,python3中是input()函數sql
1,什麼是GIL?數據庫
GIL全局解釋器鎖
在同一個進程裏的每個線程同一時間只能有一個線程訪問cpu,只要在多線程/進程之間用到全局 變量就要加上鎖
2,python中@staticmethod和@classmethod的區別?
@classmethod(cls):類方法,類名去調用,它會將類空間傳給cls
@staticmethod():靜態方法,不用傳入類空間,對象空間的方法,至關於普通函數.
3,python裏面如何拷貝一個對象,並解釋深淺拷貝
淺拷貝:第一層建立的是新的內存地址,而從第二層開始,指向的都是同一個內存地址,因此,對於第二層及更深的層數來講,保持一致性
深拷貝:徹底獨立(複製其數據對象完徹底全放獨立的一個內存,徹底拷貝,數據不共享)
4,python裏面search()和math()的區別
search():從左到右找,找到第一個就返回,找不到返回None match():從開頭找,找不到報錯,至關於在前面加個"^"
5,簡述迭代器生成器以及他們的區別
迭代器就是用於迭代操做的的對象,聽從迭代協議(內部實現了__iter__()和__next__()方法,能夠像列表(可迭代對象,只有__iter__()方法)同樣迭代獲取其中的值,與列表不一樣的是,構建迭代器的時候,不像列表同樣一次性把數據加到內存,而是以一種延遲計算的方式返回元素,即調用next方法時候返回此值。
迭代器取值:__next__,或者for循環
生成器本質上也是一個迭代器,本身實現了可迭代協議,與生成器不一樣的是生成器的實現方式不一樣,能夠經過生成器表達式和生成器函數兩種方式實現,代碼更簡潔。生成器和迭代器都是惰性可迭代對象,只能遍歷一次,數據取完拋出Stopiteration異常
生成式取值:一個yield對應一個next
6,什麼是協程,python的協程是如何實現的
協程:能在一條線程的基礎上,在多個任務之間互相切換
協程的實現:
import gevent def test1(): print(1,2) gevent.sleep(0)#執行到這裏的時候切換去函數test2 print(3,4) def test2(): print(5,6) gevent.sleep(0) print(7,8) gevent.joinall( [gevent.spawn(test1),gevent.spawn(test2)] )#在函數test1等待的時候,協程去執行了函數test2
7,什麼是裝飾器,請用裝飾器實現singleton
裝飾器:裝飾器的本質是閉包函數,功能,在不改變原函數的基礎上,爲原函數增長一些額外的功能
# 使用裝飾器實現單例模式 def singleton(cls, *args, **kwargs): instance = {} def _instance(): if cls not in instance: instance[cls] = cls(*args, *kwargs) return instance[cls] return _instance @singleton class Test_singleton: def __init__(self): self.num = 0 def add(self): self.num = 99 ts1 = Test_singleton() ts2 = Test_singleton() print(ts1) print(ts2)
8,請使用python實現快速排序
一行代碼實現: quick_sort = lambda array: array if len(array) <= 1 else quick_sort([item for item in array[1:] if item <= array[0]]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])
#常見快排 def quick_sort(array, left, right): if left >= right: return low = left high = right key = array[low] while left < right: while left < right and array[right] > key: right -= 1 array[left] = array[right] while left < right and array[left] <= key: left += 1 array[right] = array[left] array[right] = key quick_sort(array, low, left - 1) quick_sort(array, left + 1, high)
#算法中的快排 def quick_sort(array, l, r): if l < r: q = partition(array, l, r) quick_sort(array, l, q - 1) quick_sort(array, q + 1, r) def partition(array, l, r): x = array[r] i = l - 1 for j in range(l, r): if array[j] <= x: i += 1 array[i], array[j] = array[j], array[i] array[i + 1], array[r] = array[r], array[i+1] return i + 1
9,簡述select和epoll的原理和區別
select原理概述 調用select時,會發生如下事情: 從用戶空間拷貝fd_set到內核空間; 註冊回調函數__pollwait; 遍歷全部fd,對所有指定設備作一次poll(這裏的poll是一個文件操做,它有兩個參數,一個是文件fd自己,一個是當設備還沒有就緒時調用的回調函數__pollwait,這個函數把設備本身特有的等待隊列傳給內核,讓內核把當前的進程掛載到其中); 當設備就緒時,設備就會喚醒在本身特有等待隊列中的【全部】節點,因而當前進程就獲取到了完成的信號。poll文件操做返回的是一組標準的掩碼,其中的各個位指示當前的不一樣的就緒狀態(全0爲沒有任何事件觸發),根據mask可對fd_set賦值; 若是全部設備返回的掩碼都沒有顯示任何的事件觸發,就去掉回調函數的函數指針,進入有限時的睡眠狀態,再恢復和不斷作poll,再做有限時的睡眠,直到其中一個設備有事件觸發爲止。 只要有事件觸發,系統調用返回,將fd_set從內核空間拷貝到用戶空間,回到用戶態,用戶就能夠對相關的fd做進一步的讀或者寫操做了。 epoll原理概述 調用epoll_create時,作了如下事情: 內核幫咱們在epoll文件系統裏建了個file結點; 在內核cache裏建了個紅黑樹用於存儲之後epoll_ctl傳來的socket; 創建一個list鏈表,用於存儲準備就緒的事件。 調用epoll_ctl時,作了如下事情: 把socket放到epoll文件系統裏file對象對應的紅黑樹上; 給內核中斷處理程序註冊一個回調函數,告訴內核,若是這個句柄的中斷到了,就把它放到準備就緒list鏈表裏。 調用epoll_wait時,作了如下事情: 觀察list鏈表裏有沒有數據。有數據就返回,沒有數據就sleep,等到timeout時間到後即便鏈表沒數據也返回。並且,一般狀況下即便咱們要監控百萬計的句柄,大多一次也只返回不多量的準備就緒句柄而已,因此,epoll_wait僅須要從內核態copy少許的句柄到用戶態而已。 對比 select缺點: 最大併發數限制:使用32個整數的32位,即32*32=1024來標識fd,雖然可修改,可是有如下第二點的瓶頸; 效率低:每次都會線性掃描整個fd_set,集合越大速度越慢; 內核/用戶空間內存拷貝問題。 epoll的提高: 自己沒有最大併發鏈接的限制,僅受系統中進程能打開的最大文件數目限制; 效率提高:只有活躍的socket纔會主動的去調用callback函數; 省去沒必要要的內存拷貝:epoll經過內核與用戶空間mmap同一塊內存實現。 固然,以上的優缺點僅僅是特定場景下的狀況:高併發,且任一時間只有少數socket是活躍的。 若是在併發量低,socket都比較活躍的狀況下,select就不見得比epoll慢了(就像咱們經常說快排比插入排序快,可是在特定狀況下這並不成立)。
10,簡述python的垃圾回收機制
垃圾回收 Python的GC模塊主要運用了引用計數來跟蹤和回收垃圾。在引用計數的基礎上,還能夠經過「標記-清除」解決容器對象可能產生的循環引用的問題。經過分代回收以空間換取時間進一步提升垃圾回收的效率。 引用計數 原理:當一個對象的引用被建立或者複製時,對象的引用計數加1;當一個對象的引用被銷燬時,對象的引用計數減1,當對象的引用計數減小爲0時,就意味着對象已經再沒有被使用了,能夠將其內存釋放掉。 優勢:引用計數有一個很大的優勢,即實時性,任何內存,一旦沒有指向它的引用,就會被當即回收,而其餘的垃圾收集技術必須在某種特殊條件下才能進行無效內存的回收。 缺點:可是它也有弱點,引用計數機制所帶來的維護引用計數的額外操做與Python運行中所進行的內存分配和釋放,引用賦值的次數是成正比的,這顯然比其它那些垃圾收集技術所帶來的額外操做只是與待回收的內存數量有關的效率要低。同時,引用技術還存在另一個很大的問題-循環引用,由於對象之間相互引用,每一個對象的引用都不會爲0,因此這些對象所佔用的內存始終都不會被釋放掉。以下: a = [] b = [] a.append(b) b.append(a) print a [[[…]]] print b [[[…]]] 標記-清除 標記-清除只關注那些可能會產生循環引用的對象,顯然,像是PyIntObject、PyStringObject這些不可變對象是不可能產生循環引用的,由於它們內部不可能持有其它對象的引用。Python中的循環引用老是發生在container對象之間,也就是可以在內部持有其它對象的對象,好比list、dict、class等等。這也使得該方法帶來的開銷只依賴於container對象的的數量??? 原理:1. 尋找跟對象(root object)的集合做爲垃圾檢測動做的起點,跟對象也就是一些全局引用和函數棧中的引用,這些引用所指向的對象是不可被刪除的;2. 從root object集合出發,沿着root object集合中的每個引用,若是可以到達某個對象,則說明這個對象是可達的,那麼就不會被刪除,這個過程就是垃圾檢測階段;3. 當檢測階段結束之後,全部的對象就分紅可達和不可達兩部分,全部的可達對象都進行保留,其它的不可達對象所佔用的內存將會被回收,這就是垃圾回收階段。(底層採用的是鏈表將這些集合的對象鏈接在一塊兒) 缺點:標記和清除的過程效率不高。 分代回收 原理:將系統中的全部內存塊根據其存活時間劃分爲不一樣的集合,每個集合就成爲一個「代」,Python默認定義了三代對象集合,垃圾收集的頻率隨着「代」的存活時間的增大而減少。也就是說,活得越長的對象,就越不多是垃圾,就應該減小對它的垃圾收集頻率。那麼如何來衡量這個存活時間:一般是利用幾回垃圾收集動做來衡量,若是一個對象通過的垃圾收集次數越多,能夠得出:該對象存活時間就越長。
11,寫一個簡單的python socket編程
server端: import socket sk = socket.socket() # 建立客戶套接字 sk.bind(('127.0.0.1',8898)) #把地址綁定到套接字 sk.listen() #監聽連接 conn,addr = sk.accept() #接受客戶端連接 ret = conn.recv(1024) #接收客戶端信息 print(ret) #打印客戶端信息 conn.send(b'hi') #向客戶端發送信息 conn.close() #關閉客戶端套接字 sk.close() #關閉服務器套接字(可選) client端: import socket sk = socket.socket() # 建立客戶套接字 sk.connect(('127.0.0.1',8898)) # 嘗試鏈接服務器 sk.send(b'hello!') ret = sk.recv(1024) # 對話(發送/接收) print(ret) sk.close() # 關閉客戶套接字
12,下面是我輸出結果是什麼?
#下面代碼會輸出什麼 def f(x,l=[]): for i in range(x): l.append(i*i) print(l) f(2) #[0, 1] f(3,[3,2,1]) #[3, 2, 1, 0, 1, 4] f(3) #[0, 1, 0, 1, 4]
#下面代碼會輸出什麼 class Parent(object): x=1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x,Child1.x,Child2.x) #1 1 1 print(Parent.x,Child1.x,Child2.x) #1 2 1 Parent.x=3 print(Parent.x,Child1.x,Child2.x) #3 2 3[6, 6, 6, 6]
#下面代碼會輸出什麼 def multipliers(): return [lambda x:i*x for i in range(4)] print([m(2) for m in multipliers()]) #[6, 6, 6, 6]
13,Git的經常使用命令
14,列表去重(不使用set,用基本的方法實現):list=[9,4,2,5,8,4,5,3]
def quchong(list1): list2=[]; for i in list1: if i not in list2: list2.append(i); print(list2); list1 = [9, 4, 2, 5, 8,4,5,3]; quchong(list1)
15,單例模式實現
import threading import time class Foo(object): _instance = None _lock = threading.RLock() def __new__(cls, *args, **kwargs): if cls._instance: return cls._instance with cls._lock: if not cls._instance: cls._instance = object.__new__(cls) return cls._instance def task(): obj = Foo() print(obj) for i in range(10): t = threading.Thread(target=task) t.start() time.sleep(100) obj = Foo()
16,python自帶的數據類型
數字、字符串、Bytes、列表、元組、字典、集合、布爾等
17,說說==以及is的區別
==比較數值
is比較內存地址
18,python函數中*args和**kwargs這兩個參數是什麼意思
1:*args的功能:------接收多個位置參數,轉換成元組tuple形式 2:**kwargs的功能------接收多個關鍵字參數,轉換成字典dict形式 3:位置參數必定要在關鍵字參數以前,也就是(*args,**kwargs)
19,什麼是lambda函數,它有什麼好處
什麼是lamda函數? lambda 函數是一個能夠接收任意多個參數(包括可選參數)而且返回單個表達式值的函數。 (注意:lambda 函數不能包含命令,它們所包含的表達式不能超過一個) lamda函數有什麼好處? 1、lambda函數比較輕便,即用即仍,很適合須要完成一項功能,可是此功能只在此一處使用,連名字都很隨意的狀況下; 2、匿名函數,通常用來給filter,map這樣的函數式編程服務; 三、做爲回調函數,傳遞給某些應用,好比消息處理
20,用過的標準包以及第三方包(os以及sys)
標準包:內置模塊? """ os time & datetime random hashlib sys re logging json pickle """ # 11. 第三方模塊 """ requsts bs4 pymysql pymongo gevent
21,range和xrange的區別
range: range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個序列。注意這裏是生成一個序列。 xrange的用法與range相同,即xrange([start,] stop[, step])根據start與stop指定的範圍以及step設定的步長,他所不一樣的是xrange並非生成序列,而是做爲一個生成器。即他的數據生成一個取出一個。 因此相對來講,xrange比range性能優化不少,由於他不須要一會兒開闢一塊很大的內存,特別是數據量比較大的時候。 注意:1、xrange和range這兩個基本是使用在循環的時候。 二、 當須要輸出一個列表的時候,就必需要使用range了。
22,線程,進程的區別
進程:資源分配的最小單位
線程:CPU調度的最小單位
進程:IO密集型/計算密集型 提升併發,資源浪費. 線程:IO密集型提升併發,多個線程 協程:IO密集型提供併發,1個線程 計算密集型:進程 IO密集型:線程 < 協程
區別:
一、 一個程序中至少有一個進程,一個進程中至少有一個線程;
二、 線程的劃分尺度小於進程(佔有資源),使得多線程程序的併發性高;
三、 進程運行過程當中擁有獨立的內存空間,而線程之間共享內存,從而極大的提升了程序的運行效率
四、 線程不能獨立運行,必須存在於進程中
優缺點:
線程開銷小,可是不利於資源的管理和保護,而進程反之。
23,描述對python中數據類型列表list,字典 dict,元組 tuple的理解
元組:()用元括弧括起來的一組元素集合。其特色是內容不可變,即一旦定義其長度和內容都是固定的;相似於C詢言的數組。如: t = (0, True, ‘a’) 上面就定義了一個包含3個子元素的元組列表,訪問元組成員的格式是使用成員下標,如: print t(1) True (理解爲C的數組) 列表:[]由中括弧括起來的包含一組元素的集合;其特色是長度和內容均可以改變。定義以下: L = [0, False, ‘l’] 列表能夠進行以下操做: 添加元素:L.append(1) 刪除元素:del L[0] 插入元素:L.insert(2, 3) 修改元素:L[1] = True (理解爲java鏈表數組) 字典:{}Python中的字典和其它詢言的字典是一個意思,是對hashmap的實現;其詢法定義爲: d = {‘k1’: ‘k’, ‘k2’: ‘k2’} 字典能夠有以下操做: 增長鍵值對:d[‘k3’] = 3 刪除鍵值對:del d[‘k’] 修改鍵值對:d[‘k2’] = True 獲取鍵值: d[‘k1’]
24,如何刪除一個list中的元素,如何刪除dict中的一對kv
l1 = ["alex","wusir"]
l1.remove("alex")
dic = {'name':'老男孩','age':56,'hobby':'women'} del dic['name']
25,如何查找一個字符串中特定字符?Find()和index()兩個函數有什麼差別?
都是經過元素找索引:
find()方法:查找子字符串,若找到返回從0開始的下標值,若找不到返回-1
index方法是在字符串裏查找子串第一次出現的位置,若是查找不到子串,會拋出異常,
26,使用過python哪些第三方件?
1.Web框架 Django: 開源Web開發框架,它鼓勵快速開發,並遵循MVC設計,開發週期短。 ActiveGrid: 企業級的Web2.0解決方案。 Karrigell: 簡單的Web框架,自身包含了Web服務,py腳本引擎和純python的數據庫PyDBLite。 Tornado: 一個輕量級的Web框架,內置非阻塞式服務器,並且速度至關快 webpy: 一個小巧靈活的Web框架,雖然簡單可是功能強大。 CherryPy: 基於Python的Web應用程序開發框架。 Pylons: 基於Python的一個極其高效和可靠的Web開發框架。 Zope: 開源的Web應用服務器。 TurboGears: 基於Python的MVC風格的Web應用程序框架。 Twisted: 流行的網絡編程庫,大型Web框架。 Quixote: Web開發框架。 2.科學計算 Matplotlib: 用Python實現的類matlab的第三方庫,用以繪製一些高質量的數學二維圖形。 SciPy: 基於Python的matlab實現,旨在實現matlab的全部功能。 NumPy: 基於Python的科學計算第三方庫,提供了矩陣,線性代數,傅立葉變換等等的解決方案。 3.GUI PyGtk: 基於Python的GUI程序開發GTK+庫。 PyQt: 用於Python的QT開發庫。 WxPython: Python下的GUI編程框架,與MFC的架構類似。 4.其它 BeautifulSoup: 基於Python的HTML/XML解析器,簡單易用。 PIL: 基於Python的圖像處理庫,功能強大,對圖形文件的格式支持普遍。 PyGame: 基於Python的多媒體開發和遊戲軟件開發模塊。 Py2exe: 將python腳本轉換爲windows上能夠獨立運行的可執行程序。
27,描述一下MVC架構
MVC是一種架構設計模式,是一種設計理念。是爲了達到分層設計的目的,從而使代碼解耦,便於維護和代碼的複用。MVC是3個單詞的縮寫,全稱:Model-View-Controller(模型-視圖-控制器)。
一、Model
模型層,能夠簡單理解就是數據層,用於提供數據。在項目中,(簡單理解)通常把數據訪問和操做,好比將對象關係映射這樣的代碼做爲Model層,也就是對數據庫的操做這一些列的代碼做爲Model層。好比代碼中咱們會寫DAO和DTO類型的代碼,那這個DAO和DTO咱們能夠理解爲是屬於Model層的代碼。
二、View
視圖層,就是UI界面,用於跟用戶進行交互。通常全部的JSP、Html等頁面就是View層。
三、Controller
控制層,Controller層的功能就是將Model和View層進行關聯。好比View主要是顯示數據的,可是數據又須要Model去訪問,這樣的話,View會先告訴Controller,而後Controller再告訴Model,Model請求完數據以後,再告訴View。這樣View就能夠顯示數據了。
28,描述一下表與視圖的理解
數據庫中的數據都是存儲在表中的,而視圖只是一個或多個表依照某個條件組合而成的結果集,通常來講你能夠用update,insert,delete等sql語句修改表中的數據,而對視圖只能進行select操做。可是也存在可更新的視圖,對於這類視圖的update,insert和delete等操做最終會做用於與其相關的表中數據。所以,表是數據庫中數據存儲的基礎,而視圖只是爲了知足某種查詢要求而創建的一個對象。
表是物理存在的,你能夠理解成計算機中的文件!
視圖是虛擬的內存表,你能夠理解成Windows的快捷方式!
區別:一、視圖是已經編譯好的sql語句。而表不是
二、視圖沒有實際的物理記錄。而表有。
三、表是內容,視圖是窗口
四、表只用物理空間而視圖不佔用物理空間,視圖只是邏輯概念的存在,表能夠及時對它進行修改,但視圖只能有建立的語句來修改
五、表是內模式,視圖是外模式
六、視圖是查看數據表的一種方法,能夠查詢數據表中某些字段構成的數據,只是一些SQL語句的集合。從安全的角度說,視圖能夠不給用戶接觸數據表,從而不知道表結構。
七、表屬於全局模式中的表,是實表;視圖屬於局部模式的表,是虛表。
八、視圖的創建和刪除隻影響視圖自己,不影響對應的基本表。
29,有0<x<=10,10<x<=20,20<x<=30,......,190<x<=200,200<x這樣的 21個區間分別對應1-21二十一個級別,請編寫一個函數level(x)根據輸入數值返回對應級別.
30,有一個數據結構以下所示,請編寫一個函數從該結構數據中返回由指定的字段和對應的值組成的字典,若是指定字段不存在,則跳過該字段.
data:{"time":"2016-08-05T13:13:05",
"some_id":"ID1234",
"grp1":{"fld1":1,
"fld2":2},
"xxx2":{"fld3":0,
"fld5":0.4},
"fld6":11,
"fld7":7,
"fld46":8}
fields:由"|"鏈接的一以"fld"開頭的字符串,如:fld2|fld3|fld7|fld19
def select(data,fields):
#Todo:implementation
return result
data={'time':'2016-08-05T13;13:05', 'some_ID':'ID1234', 'graps1':{'fld1':1,'fld2':2}, 'xxx2':{'fld3':0,'fld5':0.4}, 'fld6':11, 'fld7':7, 'fld':8 } # 類遞歸思想 # 棧的思想 fields = 'fld2|fld3|fld7|fld9' fields_lst = fields.split('|') #['fld2', 'fld3', 'fld7', 'fld9'] result = {} data_lst = [1] while data != 1: for key in data: if key in fields_lst: result[key] = data[key] if type(data[key]) == dict: data_lst.append(data[key]) data = data_lst.pop() print(result)
#思路一: def select(data,fields): result = {} field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: res = select(data[key],fields) result.update(res) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' print(select(data,fields))
#思路二: def select(data,fields,result = {}): field_lst = fields.split('|') for key in data: if key in field_lst: result[key] = data[key] elif type(data[key]) == dict: select(data[key], fields) return result data={"time":"2016-08-05T13:13:05", "some_id":"ID1234", "grp1":{ "fld1":1,"fld2":2}, "xxx2":{ "fld3":0,"fld5":0.4}, "fld6":11, "fld7":7, "fld46":8} fields = 'fld2|fld3|fld7|fld19' select(data,fields) print(select(data,fields))
31,斐波契納數列1,2,3,5,8,13,21......根據這樣的規律,編程求出400萬之內最大的斐波契納數,並求出它是第幾個斐波契納數
li=[1,2] while li[-1]<4000000: li.append(li[-1]+li[-2]) del li[-1] print(li[-1]) print(len(li))
def func(x): if x <= 3: return x else: first = 2 second = 3 for i in range(3,x-1): value = first + second first = second second = value return first+second print func(32)
32,上機編程實現如下功能:
dicta = {"a":1,"b":2,"c":3,"d":4,"f":"hello"}
dictb = {"b":3,"d":5,"e":7,"m":9,"k":"world"}
要求寫一段代碼,實現兩個字典的相加,不一樣的key對應的值保留,相同的key對應的值相加後保留,若是是字符串就拼接,如上示例獲得結果爲:
dictc={"a":1,"b":5,"c";3,"d":9,"e":7,"m":9,"f":"hello","k":"world"}
dicta={'a':1,'b':2,'c':3,'d':4,'f':'hello'} dictb={'b':3,'d':5,'e':7,'m':9,'k':'world'} dic={} for key1 in dicta: for key2 in dictb: if key1==key2: dic[key1]=dicta[key1]+dictb[key2] for a in dicta: if a not in dic: dic[a]=dicta[a] for b in dictb: if b not in dic: dic[b]=dictb[b] print(dic)
3、Python部分
一、 __new__.__init__區別,如何實現單例模式,有什麼優勢
__new__是一個靜態方法,__init__是一個實例方法
__new__返回一個建立的實例,__init__什麼都不返回
__new__返回一個cls的實例時後面的__init__才能被調用
當建立一個新實例時調用__new__,初始化一個實例時調用__init__
二、深淺拷貝
淺拷貝只是增長了一個指針指向一個存在的地址,而深拷貝是增長一個指針而且開闢了新的內存,這個增長的指針指向這個新的內存,
採用淺拷貝的狀況,釋放內存,會釋放同一內存,深拷貝就不會出現釋放同一內存的錯誤
三、HTTP/IP相關協議,分別位於哪層
http協議是超文本傳輸協議,http協議是基於TCP/IP通訊協議來傳遞數據
http協議工做與c/s架構上,瀏覽器做爲http的客戶端經過URL向http服務端即web服務器發送所用請求。web服務器收到全部請求後,向客戶端發送響應信息,
http特色是短鏈接,無狀態
地址欄鍵輸入URL,按下回車以後經歷了什麼?
1.瀏覽器向DNS服務器請求解析該URL中的域名所對應的IP地址
2.解析出IP地址後,根據IP地址和默認端口80,和服務器創建TCP鏈接
3.瀏覽器發出讀取文件的http請求,該請求報文做爲TCP三次握手的第三個報文的數據發送給服務器
4.服務器對瀏覽器請求作出響應,並把對應的html文件發送給瀏覽器
5.釋放TCP鏈接
6.瀏覽器將該HMTL渲染並顯示內容
四、TCP/UDP區別
TCP協議是面向鏈接,保證高可靠性(數據無丟失,數據無失序,數據無錯誤,數據無重複達到)傳輸層協議
UDP:數據丟失,無秩序的傳輸層協議(qq基於udp協議)
五、webscoket
websocket是基於http協議的,可持續化鏈接
輪詢:瀏覽器每隔幾秒就發送一次請求,詢問服務器是否有新消息
長輪詢:客戶端發起鏈接後,若是沒有消息,就一直不返回response給客戶端,直到有消息返回,返回完以後,客戶端再次發起鏈接
六、RabbitMQ:
服務器端有Erlang語言來編寫,支持多種客戶端,只會ajax,用於分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性的方面不俗。
connection是RabbitMQ的socket鏈接,它封裝了socket部分相關協議邏輯
connectionFactroy爲connection的製造工廠
channel是咱們與RabbitMQ打交道的最重要的一個接口,大部分的業務操做是在chaanel這個接口中完成,包括定義Queue、定義Exchange、
綁定Queue與Exchange,發佈消息等
七、裝飾器
調用裝飾器實際上是一個閉包函數,爲其餘函數添加附加功能,不修改被修改的源代碼和不修改被修飾的方式,裝飾器的返回值也是一個函數對象。
好比:插入日誌、性能測試、事物處理、緩存、權限驗證等,有了裝飾器,就能夠抽離出大量與函數功能自己無關的雷同代碼並繼續重用。
八、閉包
1.必須有一個內嵌函數
2.內嵌函數必須引用外部函數的變量(該函數包含對外做用域而不是全局做用域名字的引用)
3.外部函數的返回值必須是內嵌函數
九、迭代器與生成器
迭代可迭代對象對應_iter_(方法)和迭代器對應_next_(方法)的一個過程
生成器:包括含有yield這個關鍵字,生成器也是迭代器,調動next把函數變成迭代器。
十、classmethod,staticmethod,property
類方法:將類的函數轉換成類方法,函數上裝飾@classmethod會將函數的自動傳值參數改爲cls
靜態方法:此方法至關於給類擴展一個功能,將類內的函數實例化,給類或對象使用,此時類內的函數就是普通函數,無論是類仍是實例化的對象均可以使用
實例化:類的實例化就會產生一個實例(對象),能夠理解爲類()把虛擬的東西實例化,獲得具體存在的值
十一、經常使用的狀態碼
200--服務器成功返回網頁
204--請求收到,但返回信息爲空
304--客戶端已經執行了GET,但文件未變化
400--錯誤請求,如語法錯誤
403--無權限訪問
404--請求的頁面不存在
500--服務器產生內部錯誤
十二、多進程,多線程,協程,GIL
GIL:全局解釋器鎖,是鎖在cpython解釋器上,致使同一時刻,同一進程只能有一個線程被執行
多進程:多進程模塊multiprocessing來實現,cpu密集型,IO計算型能夠用多進程
多線程:多線程模塊threading來實現,IO密集型,多線程能夠提升效率
協程:依賴於geenlet,對於多線程應用。cpu經過切片的方式來切換線程間的執行,遇到IO操做自動切換,線程切換時須要耗時,
而協成好處沒有切換的消耗,沒有鎖定概念。
進程:是資源管理單位,進行是相互獨立的,實現併發和併發
線程:是最小的執行單位,線程的出現爲了下降上下文切換的消耗,提供系統的併發性
1三、IO多路複用/異步非阻塞
IO多路複用:經過一種機制,能夠監聽多個描述符 select/poll/epoll
select:鏈接數受限,查找配對速度慢,數據由內核拷貝到用戶態
poll:改善了鏈接數,可是仍是查找配對速度慢,數據由內核拷貝到用戶態
epoll:epoll是linux下多路複用IO接口,是select/poll的加強版,它能顯著提升程序在大量併發鏈接中只有少許活躍的狀況下的系統CPU利用率
異步非阻塞:異步體如今回調上,回調就是有消息返回時告知一聲兒進程進行處理。非阻塞就是不等待,不須要進程等待下去,
繼續執行其餘操做,無論其餘進程的狀態。
1四、PEP8規範,規範的好處是什麼?
1.縮進:4個空實現縮進,儘可能不使用Tab
2.行:沒行最大長度不超過79,換行可使用反斜槓
3.命名規範:
4.註釋規範:
1五、range-and-xrange
都在循環時使用,xrange內存性能更好,xrange用法與range徹底相同,range一個生成list對象,xrange是生成器
1六、with上下文機制原理
_enter_和_exit_,上下文管理協議,即with語句,爲了讓一個對象兼容with語句,必須在這個對象類中聲明_enter_和_exit_方法,
使用with語句的目的就是把代碼塊放入with中執行,with結束後,自動完成清理工做,無須收到干預
1七、經典類、新式類
經典類遵循:深度優先,python2中
新式類遵循:廣度優先,Python3中
1八、有沒有一個工具能夠幫助查找Python的bug和進行靜態的代碼分析?
PyChecker是一個Python代碼的靜態分析工具,它能夠幫助查找Python代碼的bug,會對代碼的複雜度和格式提出警告,
Pylint是另一個工具能夠進行codingstandard檢查
1九、 Python是如何進行內存管理的
1.對象引用計數:
引用計數增長的狀況:
來保持追蹤內存中的對象,全部對象都用引用計數,一個對象分配一個新名稱
將其放入一個容器中(列表,字典,元祖)
引用計數減小的狀況:
使用del語句對對象別名顯示的銷燬
引用超出做用域或被從新賦值
sys.getrefcount()函數能夠得到對象的當前引用計數
2.標記-清除機制
3.分代技術
20、什麼是python?使用python有什麼好處?
python是一種編程語言,它有對象、模塊、線程、異常處理和自動內存管理。它簡潔,簡單、方便、容易擴展、有許多自帶的數據結果,並且它開源
2一、什麼是pickling和unpickling?
Pickle模塊讀入任何python對象,將它們轉換成字符串,而後使用dump函數將其轉儲到一個文件中——這個過程叫作pickling
反之從存儲的字符串文件中提取原始python對象的過程,叫作unpickling
2二、python是如何被解釋的?
Python是一種解釋性語言,它的源代碼能夠直接運行,Python解釋器會將源代碼轉換成中間語言,以後再翻譯成機器碼再執行
2三、數組和元祖之間的區別是什麼?
數組和元祖之間的區別:數組內容能夠被修改,而元祖內容是隻讀的,不可被修改的,另外元祖能夠被哈希,好比做爲字典的key
2四、參數按值傳遞和引用傳遞是怎麼實現的?
python中的一切都是類,全部的變量都是一個對象的引用。引用的值是由函數肯定的,所以沒法被改變,可是若是一個對象是能夠被修改的,你能夠改動對象
2五、Python都有哪些自帶的數據結構?
Python自帶的數據結構分爲可變和不可變的:可變的有:數組、集合、字典,不可變的是:字符串、元祖、整數
2六、什麼是python的命名空間?
在python中,全部的名字都存在於一個空間中,它們在改空間中存在和被操做——這就是命名空間,它就好像一個盒子,在每一個變量名字都對應裝着一個對象,
當查詢變量的時候,會從該盒子裏面尋找相應的對象
2七、python中的unittest是什麼?
在python中,unittest是python中的單元測試框架,它擁有支持共享搭建、自動測試、在測試中暫停代碼、將不一樣測試迭代成一組
2八、*args與**kwargs
*args表明位置參數,它會接收任意多個參數並把這些參數做爲元祖傳遞給函數。**kwargs表明的關鍵字參數,返回的是字典,位置參數必定要放在關鍵字前面
2九、在Python中什麼是slicing?
slicing是一種在有序的對象類型中(數組、元祖、字符串)節選某一段的語法
30、中的docstring是什麼?
Python中文檔字符串被稱爲docstring,它在Python中的做用是爲函數、模塊和類註釋生成文檔
3一、os與sys區別:
os是模塊負責程序與操做系統的交互,提供了訪問操做系統底層的接口
sys模塊是負責程序與python解釋器的交互,提供了一系列的函數和變量,用於操控Python時運行的環境
3二、實現一個單例模式
_new_()在 _init_()以前被調用,用於生成實例對象。利用這個方法和類的屬性的特色能夠實現設計模式的單例模式。
單例模式是指建立惟一對象,單例模式設計的類只能實例,實例化1個對象
class Singleton(object):
__instance=None
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if Singleton.__instance is None:
Singleton.__instance=object.__new__(cls,*args,**kwargs)
return Singleton.__instance
33、算法(冒泡排序,選擇排序,插入排序)
冒泡:首先,列表每兩個相鄰的數,若是前面的比後邊的大,
那麼交換這兩個數,代碼關鍵點:趟和無序區,
時間複雜度爲:O(n2)
import random
def dublue_sort(li):
for i in range(len(li)-1):
exchange= False
for j in range(len(li)-i -1):
if li[j] > li[j+1]:
li[j],li[j+1] = li[j+1],li[j]
exchange = True
if not exchange:
return
return li
li=list(range(100))
random.shuffle(li)
print(li)
print(dublue_sort(li))
選擇:一趟遍歷記錄最小的數,放到第一個位置,再一趟遍歷記錄剩餘列表中最小的數,
繼續放置,代碼關鍵點:無序區和最小數的位置,時間複雜度爲:O(n2)
def select_sort(li):
for i in range(len(li)-1): #i是趟
min_loc=i
#找i位置到最後位置範圍內最小的數
for j in range(i,len(li)):
if li[j] < li[min_loc]:
min_loc = j
#和無序區第一個數做交換
li[min_loc],li[i] = li[i],li[min_loc]
return li
li=list(range(100))
random.shuffle(li)
print(select_sort(li))
插入:列表被分爲有序區和無序區兩個部分。最初有序區只有一個元素,
每次從無序區選擇一個元素,插入到有序區的位置,直到無序區變空,
代碼關鍵點:摸到的牌和手裏的牌,時間複雜度爲:O(n2)
def insert_sort(li):
for i in range(1,len(li)): #i 表明每次摸到的牌的下標
tmp=li[i]
j = i-1 # j表明手裏最後一張牌的下標
while True:
if j < 0 or tmp >= li[j]:
break
li[ j + 1] = li [j]
j -=1
li[j+1] = tmp
li=list(range(100))
print(insert_sort(li))
二分:列表查找:從列表中查找指定元素,輸入:列表、待查找元素,輸出:元素下標或未查找到元素。
二分查找,從有序列表的候選區data[0:n]開始,經過對待查找的值與候選區中間值的比較,
可使候選區減小一半。時間複雜爲:O(logn)
def bin_search(data,val):
low=0
high=len(data)-1
while low <= high :
mid= (low+high) //2
if data[mid] == val:
return mid
elif data[mid] < high :
low = mid + 1
else:
high = mid - 1
return None
print(bin_search([1,2,3,4,5,6,7,8],4))
4、RESTful API設計指南
參考地址:
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
1、協議
API與用戶的通訊協議,老是使用HTTPs協議
2、域名
應該儘可能將API部署在專用域名之下
https://api.example.com
若是肯定API很簡單,不會有進一步擴展,能夠考慮放在主域名下
https://example.org/api/
3、版本
應該將API的版本號放入URL
https://api.example.com/v1/
另外一種作法是:將版本號放在HTTP頭信息中,
4、路徑
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
5、動詞
對於資源的具體操做類型,由HTTP動詞表示
GET(SELECT):從服務器取出資源(一項或多項)。
POST(CREATE):在服務器新建一個資源。
PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)。
PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
DELETE(DELETE):從服務器刪除資源。
還有兩個不經常使用的HTTP動詞
GET /zoos:列出全部動物園
POST /zoos:新建一個動物園
GET /zoos/ID:獲取某個指定動物園的信息
PUT /zoos/ID:更新某個指定動物園的信息(提供該動物園的所有信息)
PATCH /zoos/ID:更新某個指定動物園的信息(提供該動物園的部分信息)
DELETE /zoos/ID:刪除某個動物園
GET /zoos/ID/animals:列出某個指定動物園的全部動物
DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
6、過濾信息(Filtering)
若是記錄數量不少,服務器不可能都將它們返回給用戶,API應該提供參數,過濾返回結果
?limit=10:指定返回記錄的數量
?offset=10:指定返回記錄的開始位置。
?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。
?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序。
?animal_type_id=1:指定篩選條件
7、狀態碼(Status Code)
200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - [*]:表示一個請求已經進入後臺排隊(異步任務)
204 NO CONTENT - [DELETE]:用戶刪除數據成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [*] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。
422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。
33,海灘上有一堆桃子,五隻猴子來分,第一隻猴子把這堆桃子平均分紅五分,多了一個,這隻猴子把多的一個扔到了海里,拿走了一份,第二隻猴子把剩下的四堆桃子合在一塊兒,又平均分紅五分,又多了一個,它一樣把多的一個扔到了海里,拿走了一份,第三隻,第四隻,第五隻都是這樣作的,問海灘上原來最少有多少桃子.