深圳騎士計劃脫產班全棧3期第三次統一考試python
考試時長:5個小時 滿分:150分mysql
評分標準(150分): (150, 'A+'), (136, 'A'), (129, 'B+'), (121, 'B'), (106, 'B-'), (91, 'C+'), (76, 'C'), (61, 'C-'), (0, ' D')正則表達式
1.請編寫一個函數實現將IP地址轉換成一個整數。(5分)redis
如 10.3.9.12 轉換規則爲:算法
10 00001010sql
3 00000011
編程
9 00001001瀏覽器
12 00001100
緩存
再將以上二進制拼接起來計算十進制結果:00001010 00000011 00001001 00001100 = ?
答:
# -*- coding: utf-8 -*- # __author: Tiger_Lee # @file: 考試題.py # @time: 2019 02 26 # @email: lxh661314@163.com # 贈送內容:用Python獲取本機ip地址 from socket import gethostbyname_ex, gethostname local_IP_list = gethostbyname_ex(gethostname()) local_IP = gethostbyname_ex(gethostname())[2][0] def decimal_to_binary(ip_add): """ 將ip地址轉換爲二進制 :param ip_add: :return: """ num_list = ip_add.split(".") ip_binary = "" for num in num_list: num = bin(int(num))[2:] binary_num = num.rjust(8, '0') ip_binary += binary_num + " " return ip_binary[:-1] binary_ip = decimal_to_binary(local_IP) print(binary_ip) def binary_to_decimal(binary): """ 將二進制轉換爲IP地址 :param binary: :return: """ ip_str = "" binary_list = binary.split(" ") for num in binary_list: ip_str += str(int(num, 2)) + "." return ip_str[:-1] print(binary_to_decimal(binary_ip))
2.python遞歸的默認最大層數(1分),怎麼更改其默認最大層數?(2分)(本題總分3分)
# import sys # sys.setrecursionlimit(100000) # # def func(n): # print(n) # n += 1 # func(n) # # func(0)
3.請寫出print的結果:(3分)
v1 = 1 or 3
v2 = 1 and 3
v3 = 0 and 2 and 1
v4 = 0 and 2 or 1
v5 = 0 and 2 or 1 or 4
v6 = 0 or False and 1
print(v1, v2, v3, v4, v5, v6)
答:
1,3,0,1,1,False
4.用一行代碼實現數值交換:(2分)
a = 1
b = 2
答:
a, b = b, a
5.如何安裝第三方模塊?(1分)以及用過哪些第三方模塊?(2分)(本題總分3分)
方法1:pip install 第三方模塊 方法2:pycharm中鼠標操做 用過:greenlet gevent pymysql socket
6.談談你對閉包的理解?(2分)並寫一個閉包函數。(2分)(本題總分4分)
內層函數對外層函數非全局變量的引用,該內部函數稱爲閉包函數 def func(): name = '666' def inner(): print(name) return inner f = func() f()
7.什麼是反射?(2分)以及應用場景?(2分)(本題總分4分)
經過字符串的形式操做對象相關的屬性。python中的一切事物都是對象(均可以使用反射) 應用場景: class Foo: f = '類的靜態變量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #檢測是否含有某屬性 print(hasattr(obj,'name')) print(hasattr(obj,'say_hi')) #獲取屬性 n=getattr(obj,'name') print(n) func=getattr(obj,'say_hi') func() print(getattr(obj,'aaaaaaaa','不存在啊')) #報錯 #設置屬性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) print(obj.show_name(obj)) #刪除屬性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,則報錯 print(obj.__dict__)
8.什麼是面向對象的mro?(3分)
答 :
對於你定義的每個類,Python 會計算出一個方法解析順序(Method Resolution Order, MRO)列表,它表明了新式類中類繼承的順序
9.簡述 yield和yield from關鍵字。(3分)
答 :
在python中用yield和yield from都是構造一個生成器函數 yield後面返回的是一個值 yield from則是直接返回一個生成器
10.簡述 OSI 七層協議。(寫出7層2分,簡述每一層總分3分)(本題總分5分)
答 :
應用層 網絡服務與最終用戶的一個接口。 常見協議:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP 表示層 數據的表示、安全、壓縮。(在五層模型裏面已經合併到了應用層) 格式有,JPEG、ASCll、DECOIC、加密格式等 會話層 創建、管理、終止會話。(在五層模型裏面已經合併到了應用層) 對應主機進程,指本地主機與遠程主機正在進行的會話 傳輸層 定義傳輸數據的協議端口號,以及流控和差錯校驗。 常見協議:TCP UDP,數據包一旦離開網卡即進入網絡傳輸層 常見的物理設備 :四層路由器、四層交換機 網絡層 進行邏輯地址尋址,實現不一樣網絡之間的路徑選擇。 常見協議:ICMP IGMP IP(IPV4 IPV6) ARP RARP 常見物理設備:路由器、三層交換機 數據鏈路層 創建邏輯鏈接、進行硬件地址尋址、差錯校驗 [2] 等功能。(由底層網絡定義協議) 將比特組合成字節進而組合成幀,用MAC地址訪問介質,錯誤發現但不能糾正。 ,常見協議:ARP協議 常見物理設備:網橋、以太網交換機、網卡 物理層 創建、維護、斷開物理鏈接。(由底層網絡定義協議) 常見物理設備:中繼器、集線器、雙絞線
11.什麼是C/S和B/S架構?(2分)
答 :
Client與Server ,中文意思:客戶端與服務器端架構,這種架構也是從用戶層面(也能夠是物理層面)來劃分的。 這裏的客戶端通常泛指客戶端應用程序EXE,程序須要先安裝後,才能運行在用戶的電腦上,對用戶的電腦操做系統環境依賴較大。 B/S即:Browser與Server,中文意思:瀏覽器端與服務器端架構,這種架構是從用戶層面來劃分的。 Browser瀏覽器,其實也是一種Client客戶端,只是這個客戶端不須要你們去安裝什麼應用程序,只需在瀏覽器上經過HTTP請求服務器端相關的資源(網頁資源),客戶端Browser瀏覽器就能進行增刪改查。
12.簡述 三次握手、四次揮手的流程。(4分)
TCP的三次握手 TCP是因特網中的傳輸層協議,使用三次握手協議創建鏈接。當主動方發出SYN鏈接請求後,等待對方回答SYN+ACK[1],並最終對對方的 SYN 執行 ACK 確認。這種創建鏈接的方法能夠防止產生錯誤的鏈接。[1] TCP三次握手的過程以下: 客戶端發送SYN(SEQ=x)報文給服務器端,進入SYN_SEND狀態。 服務器端收到SYN報文,迴應一個SYN (SEQ=y)ACK(ACK=x+1)報文,進入SYN_RECV狀態。 客戶端收到服務器端的SYN報文,迴應一個ACK(ACK=y+1)報文,進入Established狀態。 三次握手完成,TCP客戶端和服務器端成功地創建鏈接,能夠開始傳輸數據了。 TCP的四次揮手 創建一個鏈接須要三次握手,而終止一個鏈接要通過四次握手,這是由TCP的半關閉(half-close)形成的。 (1) 某個應用進程首先調用close,稱該端執行「主動關閉」(active close)。該端的TCP因而發送一個FIN分節,表示數據發送完畢。 (2) 接收到這個FIN的對端執行 「被動關閉」(passive close),這個FIN由TCP確認。 注意:FIN的接收也做爲一個文件結束符(end-of-file)傳遞給接收端應用進程,放在已排隊等候該應用進程接收的任何其餘數據以後,由於,FIN的接收意味着接收端應用進程在相應鏈接上再無額外數據可接收。 (3) 一段時間後,接收到這個文件結束符的應用進程將調用close關閉它的套接字。這致使它的TCP也發送一個FIN。 (4) 接收這個最終FIN的原發送端TCP(即執行主動關閉的那一端)確認這個FIN。[1] 既然每一個方向都須要一個FIN和一個ACK,所以一般須要4個分節。 注意: (1) 「一般」是指,某些狀況下,步驟1的FIN隨數據一塊兒發送,另外,步驟2和步驟3發送的分節都出自執行被動關閉那一端,有可能被合併成一個分節。[2] (2) 在步驟2與步驟3之間,從執行被動關閉一端到執行主動關閉一端流動數據是可能的,這稱爲「半關閉」(half-close)。 (3) 當一個Unix進程不管自願地(調用exit或從main函數返回)仍是非自願地(收到一個終止本進程的信號)終止時,全部打開的描述符都被關閉,這也致使仍然打開的任何TCP鏈接上也發出一個FIN。 不管是客戶仍是服務器,任何一端均可以執行主動關閉。一般狀況是,客戶執行主動關閉,可是某些協議,例如,HTTP/1.0卻由服務器執行主動關閉。[2]
13.什麼是arp協議?(2分)
地址解析協議,即ARP(Address Resolution Protocol),是根據IP地址獲取物理地址的一個TCP/IP協議。
14.TCP和UDP的區別?(3分)
TCP(Transmission Control Protocol)可靠的、面向鏈接的協議(eg:打電話)、傳輸效率低全雙工通訊(發送緩存&接收緩存)、面向字節流。使用TCP的應用:Web瀏覽器;電子郵件、文件傳輸程序。 UDP(User Datagram Protocol)不可靠的、無鏈接的服務,傳輸效率高(發送前時延小),一對1、一對多、多對1、多對多、面向報文,盡最大努力服務,無擁塞控制。使用UDP的應用:域名系統 (DNS);視頻流;IP語音(VoIP)。
15.爲什麼基於tcp協議的通訊比基於udp協議的通訊更可靠?(2分)
當客戶和服務器彼此交換數據前,必須先在雙方之間創建一個TCP鏈接,以後才能傳輸數據。TCP提供超時重發,丟棄重複數據,流量控制等功能,保證能從一端傳到另外一端。
16.什麼是粘包?(1分) socket 中形成粘包的緣由是什麼?(2分) 哪些狀況會發生粘包現象?(2分)(本題總分5分)
粘包 :在tcp協議中,幾條連續發送的數據在接收端粘在一塊兒。 粘包成因 :本質是發送信息與接受信息的邊界不清晰形成的 哪些狀況會發生粘包 :發送端的緩存機制、接收端的緩存機制
17.什麼是進程?(2分)請簡述進程的三個狀態?(2分)(本題總分4分)
在運行中的程序就是進程 進程是計算機中最小的資源分配單位 進程的三狀態 :就緒 運行 阻塞
18.什麼是線程?(3分)
線程是計算機中能被CPU調度的最小單位
19.簡述 進程、線程、協程的區別?(3分) 以及應用場景?(3分)(本題總分6分)
進程:數據隔離,能夠利用多核,會產生數據不安全的現象。經常使用於數據隔離度高的高計算型場景 線程:數據共享,在python中不能利用多核,操做系統級別,會產生數據不安全的現象。經常使用於數據隔離度低的高IO型場景。 協程:數據共享,不能利用多核,用戶級,操做系統不可見,不存在數據安全問題。經常使用於數據隔離度低的高IO型場景。
20.GIL是什麼?(3分)
全局解釋器鎖。 該鎖是Cpython解釋器中特有的 保證了同一個python進程中的多個線程同一時刻只能有一條線程訪問CPU。
21.Python中如何使用線程池和進程池?(4分)
線程池 from concurrent.futures import ThreadPoolExecutor p = ThreadPoolExecutor(5) 進程池 from concurrent.futures import ProcessPoolExecutor p = ProcessPoolExecutor(5)
22.進程之間如何進行通訊?(3分)
能夠經過原生socket通訊 若是是在同一個進程中,也可使用multiprocessing自帶的pipe或者queue進行通訊 也可使用第三方工具:memcache、redis、kafka、rabbitmq
23.什麼是併發和並行?(3分)
並行 : 並行是指二者同時執行,好比賽跑,兩我的都在不停的往前跑;(資源夠用,好比三個線程,四核的CPU ) 併發 : 併發是指資源有限的狀況下,二者交替輪流使用資源,好比一段路(單核CPU資源)同時只能過一我的,A走一段後,讓給B,B用完繼續給A ,交替使用,目的是提升效率。
24.你知道幾種鎖(請列出)?(1分)並解釋它們的做用和區別?(3分)(本題總分4分)
互斥鎖和遞歸鎖 都是爲了保證在併發編程中的數據安全問題 互斥鎖 :在一個進程或者線程單位中只能連續調用一次,不然就會發生死鎖現象 遞歸鎖 :在Python中爲了支持在同一線程中屢次請求同一資源,python提供了可重入鎖RLock
25.解釋什麼是異步非阻塞?(4分)
異步:程序在作多件事情的時候,沒必要按照順序執行,能夠各自執行各自的不受干擾 非阻塞:程序中沒有阻塞現象
26.簡述 gevent模塊的做用和應用場景?(4分)
協程模塊 能夠用來規避單線程中的IO操做,提升線程對CPU的利用率 可用於 爬蟲等IO操做比較頻繁的網絡應用場景
27.請實現功能 : 在不改變裝飾器的狀況下,給裝飾器的執行加上log信息。(5分)
def log(wrap):
…
@log
def wrapper(func):
def inner(*args,**kwargs):
print('before func')
ret = func(*args,**kwargs)
print('after func')
return ret
return inner
@wrapper
def wahaha(name):
print('%s in wahaha'%name)
wahaha('alex')
答:
def log(wrap): def log_inner(*args,**kwargs): inn = wrap(*args,**kwargs) def inner(*args,**kwargs): ret = inn(*args,**kwargs) print(wrap.__name__,'is running') return ret return inner return log_inner @log def wrapper(func): def inner(*args,**kwargs): print('before func') ret = func(*args,**kwargs) print('after func') return ret return inner @wrapper def wahaha(name): print('%s in wahaha'%name) wahaha('alex')
28.寫代碼獲得兩個列表的交集和差集?(4分)
l1 = [1,2,3]
l2 = [2,3,4]
# 交集 print(set(l1) & set(l2)) print(set(l1).intersection(set(l2))) # 差集 print(set(l1) - set(l2)) print(set(l1).difference(set(l2)))
29.用python正則匹配字符串,<.*>和<.*?>有什麼區別?(3分)
<.*>是正則默認的貪婪匹配模式,會直接匹配到最後一個> <.*?>是正則表達式的惰性匹配模式,會匹配到第一個> 例如 <h1>hahaha<\h1> <.*> 匹配的結果是一個 <h1>hahaha<\h1> <.*?> 匹配的結果是兩個<h1>和<\h1>
30.讀代碼寫出代碼運行後的結果,並解釋執行過程?(6分)
def func(num):
n, a, b = 0, 0, 1
while n < num:
yield b
print(b, 'in func')
a, b = b, a + b
n = n + 1
for i in func(5):
print(i)
yield: 帶有yield的函數是一個迭代器,函數返回某個值時,會停留在某個位置,返回函數值後,會在前面停留的位置繼續執行,直到程序結束
結果是: 1 1 in func 1 1 in func 2 2 in func 3 3 in func 5 5 in func
31.用Python實現一個二分查找的函數。(6分)
32.讀代碼寫答案:(4分)
(1)
a = range(10)
b = range(20)
z = zip(a, b)
print(len(list(z))) # 請寫出打印結果
print(len(list(z))) # 請寫出打印結果
答:
zip() 函數用於將可迭代的對象做爲參數,將對象中對應的元素打包成一個個元組,而後返回由這些元組組成的列表。
執行結果:
10 0
(2)
def func(n):
return n % 2 == 1
newlist = filter(func, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(list(newlist)) # 請寫出打印結果
答:
filter() 函數用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。
執行結果:
[1, 3, 5, 7, 9]
(3)
a = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(list(a)) # 請寫出打印結果
答:
map() 會根據提供的函數對指定序列作映射。
執行結果:
[3, 7, 11, 15, 19]
33.讀代碼寫出打印的結果,並解釋爲何是這樣。(6分)
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
print('D')
D().func()
答案:
A C B D 這是新式類的繼承順序致使的,根據c3算法或者mro方法給出的結論均可以得出。
34.列舉你所知道的面向對象的特殊方法,及其應用?(5分,每寫一個得0.5分)
__len__ len 一個對象就會觸發 __len__方法。 __hash__()方法應該返回一個32位長的整數,對與同一個對象,__hash__()方法應該老是返回相同的值 __str__ 若是一個類中定義了__str__方法,那麼在打印 對象 時,默認輸出該方法的返回值。 __repr__ 若是一個類中定義了__repr__方法,那麼在repr(對象) 時,默認輸出該方法的返回值。 __call__ 方法的執行是由對象後加括號觸發的 __eq__ x==y 運算將會調用實例x的__eq__(self, other)方法 __del__ 析構方法,當對象在內存中被釋放時,自動觸發執行。 __new__ 構造方法__new__的執行是由建立對象觸發的,即:對象 = 類名() item系列將對象視爲字典使用時,就會觸發item方法 __getitem__ __setitem__ __delitem__ __delattr__
35.用盡可能多的方法實現單例模式。(8分)
class A: __instance = None def __init__(self,name,age): self.name =name self.age = age def __new__(cls, *args, **kwargs): if cls.__instance is None: obj = object.__new__(cls) cls.__instance = obj return cls.__instance
36.讀代碼回答其中的問題:(本題總分12分)
(1)
import threading
import time
def _wait():
time.sleep(60)
# FlagA
t = threading.Thread(target=_wait, daemon=False)
t.start()
# FlagB
# 問:程序從FlagA執行到FlagB的時間大體爲多少秒?並簡述爲何?(2分)
0秒左右,由於建立一個線程並啓動它的時間很是短。
# 問:deamon=True時 程序從FlagA執行到FlagB的時間大體爲多少秒?並簡述爲何?(2分)
0秒左右,若是設置deamon=True那麼至關於開啓了一個守護線程,守護線程會等待主線程結束以後才結束,而主線程會等待全部非守護線程子線程結束以後才結束,在程序中沒有其餘的非守護線程的子線程,所以主線程的代碼結束以後守護線程就會當即結束。
(2)
loop = int(1E7)
def _add(loop: int = 1):
global number
for _ in range(loop):
number += 1
def _sub(loop: int = 1):
global number
for _ in range(loop):
number -= 1
number = 0
ta = threading.Thread(target=_add, args=(loop,))
ts = threading.Thread(target=_sub, args=(loop,))
ta.start()
ts.start()
ta.join()
ts.join()
# 問此時的number是否必定爲零?並簡述爲何?(2分)
不必定,由於在CPU指令中,+=操做是被拆分爲兩條指令的,因此可能出現數據不安全的狀況。
(3)
number = 0
ta = threading.Thread(target=_add, args=(loop,))
ts = threading.Thread(target=_sub, args=(loop,))
ta.start()
ta.join()
ts.start()
ts.join()
# 問此時的number是否必定爲零?並簡述爲何?(2分)
會,若是加上join就使得代碼從異步變成同步了,必定不會發生數據不安全的問題。
(4)
loop = int(1E7)
def _add(loop: int = 1):
global numbers
for _ in range(loop):
numbers.append(0)
def _sub(loop: int = 1):
global numbers
for _ in range(loop):
while not numbers:
time.sleep(1E-8)
numbers.pop()
numbers = [0]
ta = threading.Thread(target=_add, args=(loop,))
ts = threading.Thread(target=_sub, args=(loop,))
ta.start()
ts.start()
ta.join()
ts.join()
# 問此時的numbers的長度是否必定爲1?並簡述爲何?(2分)
必定爲1,由於列表的append操做是線程安全的。
(5)
numbers = [0]
ta = threading.Thread(target=_add, args=(loop,))
ts = threading.Thread(target=_sub, args=(loop,))
ta.start()
ta.join()
ts.start()
ts.join()
# 問此時的numbers的長度是否必定爲1?並簡述爲何?(2分)