面試之 python基礎
1、簡述 解釋型 和 編譯型 編程語言?
編譯型語言:
- 1、預編譯:源代碼寫好後,在執行之前,編譯器直接將源代碼編譯成機器碼,只編譯一次,編譯的時候根據對應的運行環境生成機器碼,系統環境不同,編譯後的可執行文件也不同;
- 2、鏈接:把各個模塊的機器碼和依賴庫串聯起來生成 可執行文件. 優點: 執行效率高; 缺點: 跨平臺型差,開發效率低(修改代碼需要重新進行預編譯); 代表語言:c,c++,siwft
解釋型語言:
- 不需要編譯,只在運行程序的時候翻譯成機器語言。
- 每運行一次就翻譯一次.
- 優點: 跨平臺型好(前提是安裝解釋器)、開發效率高(修改代碼直接修改);
- 缺點: 執行效率低(每次運行之前都需要編譯一次);
- 代表語言: javascript, python, php, perl;
2、Python解釋器種類以及特點?
- CPython、Ipython、PyPy、Jython、IronPython
3、位和字節的關系?
- 位:bit,計算機最小單位,一個二進制數0或者1;
- 字節:1byte=8bit;
4、b、B、KB、MB、GB 的關系?
- 1 GB= 1024 MB ;1MB = 1024Kb;1KB=1024B;1B=8b
5、請至少列舉5個 PEP8 規範?
- 每一級縮進使用4個空格;
- 函數命名使用全部小寫的方式,可以使用下劃線;
- 常量命名使用全部大寫的方式,可以使用下劃線;
- 所有行限制的最大字符數為79,換行可以使用反斜杠;
6、列舉python2和python3的區別?
- print區別:py2直接使用
print ‘a‘
,py3使用print(‘a‘)
; - range區別:py2中
range(n)
返回列表,py3返回叠代器,節約內存; - 編碼區別:py2使用ascii,py3使用utf-8編碼;
- 字符串和字節串:py2中unicode表示字符串,str表示字節串;py3中str表示字符串,bytes表示字節串;
- input()函數,Py2中是
raw_input()
,py3中是input()
7、匿名函數?
需要使用函數但是又不行去命名的情況下使用。
foo = lambda x:x**2 foo() # 等價於 def foo(x): return x**2
8、pass的作用?
- 不會執行任何操作
- 保證格式完整
- 保證語義正確
9、*arg 和 **kwarg作用?
- 主要用於函數定義,將不定數量的參數傳遞給一個函數。
- *args:用來發送一個 非鍵值對 的 可變數量 的 參數列表 給一個函數
- **kwargs:允許你將 不定長度 的 鍵值對,作為參數傳遞給一個函數
10、is 和 == 的區別
- 是python標準操作符中的比較操作符,用來比較判斷兩個對象的value(值)是否相等
- 比較判斷指向的內存地址是否相同。
11、簡述Python的深淺拷貝
- 淺拷貝:只拷貝不可變元素(
str,tuple
),對 可變容器中的元素(lst,dict
)進行內存地址引用,一旦容器中元素改變,那麽引用都會改變; - 深拷貝:重新開辟空間保存所有元素,沒有共享的內存引用。
12、Python垃圾回收機制? 2
- 1、引用計數算法。當有1個變量保存了對象的引用時,例如:
a=20,b=a
,此對象的引用計數就會加1。當使用del刪除變量指向的對象時,如果對象的引用計數不為1,比如3,那麽此時只會讓這個引用計數減1,即變為2,當再次調用del時,變為1,如果再調用1次del,此時會真的把對象進行刪除; - 2、標記清除機制。等到沒有空閑內存的時候從寄存器和程序棧上的引用出發,遍歷以對象為節點、以引用為邊構成的圖,把所有可以訪問到的對象,打上標記,然後清掃一遍內存空間,把所有沒標記的對象釋放。缺點就是必須順序掃描整個堆內存。
- 3、分代技術。將系統中的所有內存塊根據其存活時間劃分為不同的集合,即“代”。垃圾收集頻率隨著“代”的存活時間的增大而減小,存活時間通常利用經過幾次垃圾回收來度量。新創建的對象都會分配在年輕代,年輕代鏈表的總數達到上限時,Python垃圾收集機制就會被觸發,把那些可以被回收的對象回收掉,而那些不會回收的對象就會被移到中年代去,依此類推,老年代中的對象是存活時間最久的對象,甚至是存活於整個系統的生命周期內。
13、Python的 可變類型 和 不可變類型?
- 1、不可變類型(數字、字符串、元組、不可變集合):不支持原地修改,只能重新申請內存空間;
- 2、可變類型(列表、字典、可變集合):可以原地修改,容器內存地址不會變。
14、列舉常見的內置函數?
dir(__builtin__) # win列出所有內置函數
abs()
pow(x,y) # x**y
round()
dir()
str()
set()
list()
max()
min()
id()
getattr()
setattr()
15、一行代碼實現 9*9 乘法表
ele = ''
for x in range(1,10):
for y in range(1,x+1):
ele= ele + '%sx%s=%s' % (x,y,x*y)+ '\t'
ele+='\n'
print(ele)
# 一行代碼實現
print('\n'.join('\t'.join(['%sx%s=%s' % (x,y,x*y) for y in range(1,x+1)]) for x in range(1,10)))
16、列舉常用模塊都有哪些?
time、datetime、collection、re、os、random、json、pickle、hashlib、subprocess。
17、re的match和search區別?
- match:從左側第一位開始匹配;
- search:從左至右逐個匹配。
18、正則表達式的貪婪和非貪婪匹配區別?
默認貪婪匹配,匹配越多越好, 非貪婪匹配在pattern後面追加
?
!In [16]: m = re.match('\d+',s) In [17]: m Out[17]: <_sre.SRE_Match object; span=(0, 2), match='12'> In [18]: m = re.match('\d+?',s) In [19]: m Out[19]: <_sre.SRE_Match object; span=(0, 1), match='1'>
19、如何實現[‘1’,’2’,’3’]
變成[1,2,3]
?
# 原地修改
lst = ['1', '2', '3']
for k,v in enumerate(lst):
lst[k] = int(v)
print(lst)
# 創建新列表
l1 = [int(x) for x in lst]
print(l1)
# map_reduce原地修改
lst = list(map(lambda x:int(x),lst))
print(lst)
20、如何用一行代碼生成[1,4,9,16,25,36,49,64,81,100]
?
print([i**2 for i in range(1,11)])
21、談談你對閉包的理解?
- 1、函數中定義嵌套函數;
- 2、外層函數返回內層嵌套函數的引用;
- 3、內層函數引用外層函數的變量。
22、__new__
和__init__
區別?
__new__
是在實例創建之前被調用的,因為它的任務就是創建一個空實例然後將其返回,是個靜態方法;__init__
是當實例對象創建完成後才被調用,可以設置對象屬性的一些初始值。
23、你知道幾種設計模式?
24、編碼和解碼你了解過麽?
- 編碼:將字符按照特定的規則轉換成二進制;
- 解碼:按照對應的解碼規則 將二進制代碼轉換成字符;
編碼規則有:
ascii 1byte gbk 2byte unicode 2byte 包含與所有字符的映射關系,內存中的通用格式 utf8 可變長,漢字3bytes,字母1byte,傳輸時候可以用utf8編碼
25、列表推導list comprehension和生成器的優劣。
- 都是可叠代對象,可以使用for循環;
- 生成器存儲的算法,當序列比較大的時候,生成器可以節約內存,但是生成器是一次性的,叠代完後就自動銷毀
26、什麽是裝飾器?如果想在函數之後進行裝飾,應該怎麽做?
- 在不改變原函數的情況下對原函數的功能進行擴展,裝飾器本質上是閉包函數。
27、手寫個使用裝飾器實現的單例模式?
def singleton(cls):
instance = {}
def _singleton(*args):
if cls not in instance:
# 調用類的init方法,采用dict模式其他類可以重復使用
instance[cls] = cls(*args)
return instance[cls]
return _singleton
@singleton
class People(object):
def __init__(self,name, age):
self.name=name
self.age=age
def add(self):
pass
s = People('alex',23)
s1 = People('kate',28)
print(s==s1) # True
28、使用裝飾器的單例和使用其他方法的單例,在後續使用中,有何區別?
- 代碼重用
29、手寫正則郵箱地址
pattern = '[1-9a-z]+@(qq|126|163|gmail|foxmail|yahoo)\.com'
import re
m = re.match(pattern,s)
print(m.group())
30、多進程與多線程的區別?CPU密集型適合用什麽?
31、介紹下協程,為何比線程還快?
- 程下的並發,用戶程序級別實現任務切換,而線程是解釋器級別的;
- gevent模塊實現偽多線程。
面試之 python基礎