python常見問題一
1、迭代器和生成器函式區別?
答:(1)迭代器是一個更抽象的概念,任何物件,如果它的類有 next 方法和 iter方法返回自己本身。對於 string、list、dict、tuple 等這類容器物件,使用 for 迴圈遍歷是很方便的。在後臺 for 語句對容器物件呼叫 iter()函式,iter()是 python的內建函式。iter()會返回一個定義了next()方法的迭代器物件,它在容器中逐個訪問容器內元素,next()也是 python的內建函式。在沒有後續元素時,next()會丟擲一個 StopIteration 異常
(2)生成器(Generator)是建立迭代器的簡單而強大的工具。它們寫起來就像是正規的函式,只是在需要返回資料的時候使用 yield 語句。每次 next()被呼叫時,生成器會返回它脫離的位置(它記憶語句最後一次執行的位置和所有的資料值)
區別:生成器能做到迭代器能做的所有事,而且因為自動建立了__iter__()和 next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表示式取代列表解析可以同時節省記憶體。除了建立和儲存程式狀態的自動方法,當發生器終結時,還會自動丟擲 StopIteration 異常
2、迭代器的實現?
答:
class Squares(object):
def __init__(self, start, stop):
self.start = start
self.stop = stop
def __iter__(self):
return self
def next(self):
if self.start >= self.stop:
raise StopIteration
current = self.start * self.start
self.start += 1
return current
3、輸入目錄,輸出列印 全部檔案以及資料夾
答:
#encoding=utf-8
import os
directory = raw_input("pls enter dir:")
list_dirs = os.listdir(directory)
for df in list_dirs:
path = os.path.join(directory, df)
print path
4、os.path 和 sys.path 區別
答: os.path 是一個模組,用來處理目錄、路徑相關的模組。
sys.path 是一個列表,返回直譯器相關的目錄列表、環境變數、登錄檔等初始化
資訊
5、range 和 xrange 區別
答:range 會直接生成一個 list 物件,而 xrange 則不會直接生成一個 list,而是每次呼叫返回其中的一個值,xrange 是一個生成器
6、裝飾器: 求函式執行時間,列印日誌
答:
def benchmark(func):
"""
裝飾器列印一個函式的執行時間
"""
import time
def wrapper(*args, **kwargs):
t = time.clock()
res = func(*args, **kwargs)
print func.__name__, time.clock()-t
return res
return wrapper
def logging(func):
"""
裝飾器記錄函式日誌
"""
def wrapper(*args, **kwargs):
res = func(*args, **kwargs)
print func.__name__, args, kwargs
return res
return wrapper
@benchmark
@logging
def reverse_string(string):
return str(string)
7、import 方法:匯入順序
答:推薦所有的模組在 Python 模組的開頭部分匯入。 而且最好按照這樣的順
序:
(1)Python 標準庫模組
(2)Python 第三方模組
(3)應用程式自定義模組
8、python 裡如何實現 tuple 和 list 的轉換
答:可以通過 python 內建函式去轉換
A=(1,2,3)
B = list(A)
C = tuple(B)
9、如何用 python 來進行查詢和替換一個文字字串
答:可以通過 string 型別裡的 find()函式實現查詢,replace()函式去替換
10、python 正則匹配裡 search()和 match()的區別?
答:re.match() 從第一個字元開始找, 如果第一個字元就不匹配就返回 None, 不繼續匹配. 用於判斷字串開頭或整個字串是否匹配,速度快.
re.search() 會整個字串查詢,直到找到一個匹配
11、python 裡如何生成隨機數
答:通過 random 模組,使用例如 random.randint,random.randrange 函式
12、python 裡如何拷貝一個物件
答:python 裡面有深拷貝淺拷貝之說,可以使用 copy 模組裡的 copy 函式實現淺拷貝,copy.deepcopy 實現深拷貝
13、如何在一個 function 裡設定一個全域性變數
答:通過在函式中指定 global 關鍵字
a = 2
def func():
global a
print a
func()
14、怎樣在 python 中拼接字串
答:可以直接通過字串相加操作,s=”123”,s+”234”,或者兩變數相加 l=”456”,s+l
15、實現 string->float,但要逐個字元的去解析,不能呼叫已有的函
數
答:
def my_float(s):
''‘字串轉換成 float'''
value = 0.0
dot_position = 0
status = False
for ch in s:
if ch != '.' :
alue = value*10 + (ord(ch) - 48)
if not status:
dot_position += 1
else:
status = True
return value/(10 ** (len(s)-dot_position-1))
16、python 中 yield 的用法
答:yield 簡單說來就是一個生成器,生成器是這樣一個函式,它記住上一次返回時在函式體中的位置。對生成器函式的第二次(或第 n 次)呼叫跳轉至該函式中間,而上次呼叫的所有區域性變數都保持不變。
17、xrange 和 range 的區別
答:xrange 用法與 range 完全相同,所不同的是生成的不是一個 list 物件,而是一個生成器。Xrange 不會上來就開闢一個空間,迴圈用 xrange 比較好
18、map(),reduce()的用法
答:(1)map(function, sequence[, sequence, ...]) -> list
function:是一個函式
sequence:是一個或多個序列,取決於 function 需要幾個引數
返回值是一個 list
(2)reduce(function, sequence[, initial]) -> value
function:該函式有兩個引數
sequence:序列可以是 str,tuple,list
initial:固定初始值
19、一句話的乘階函式
答:reduce(lambda x,y: x*y, range(1,n+1))
20、介紹一下 except 的用法和作用
答:except: #捕獲所有異常
except: <異常名>: #捕獲指定異常
except:<異常名 1,異常名 2):捕獲異常 1 或者異常 2
except:<異常名>,<資料>:捕獲指定異常及其附加的資料
except:<異常名 1,異常名 2>:<資料>:捕獲異常名1 或者異常名 2,及附加的資料庫
21、簡述 python 是如何進行記憶體管理機制和引用計數
答:Python 作為一種動態型別的語言,其物件和引用分離,Python 採取了一種相對簡單的垃圾回收機制,即引用計數。垃圾回收(Garbage Collection)python 提供了 del 方法來刪除某個變數,它的作用是讓某個物件引用數減少 1。當某個物件引用數變為 0 時並不是直接將它從記憶體空間中清除掉,而是採用垃圾回收機制 gc 模組,當這些引用數為 0 的變數規模達到一定規模,就自動啟動垃圾回收,將那些引用數為 0 的物件所佔的記憶體空間釋放。這裡 gc 模組採用了分代回收方法,將物件根據存活的時間分為三“代”,所有新建的物件都是 0 代,當 0 代物件經過一次自動垃圾回收,沒有被釋放的物件會被歸入 1 代,同理 1 代歸入 2 代。每次當 0 代物件中引用數為 0 的物件超過 700 個時,啟動一次 0 代物件掃描垃圾回收,經過 10 次的 0 代回收,就進行一次 0 代和 1 代回收,1 代回收次數超過10 次,就會進行一次 0 代、1 代和 2代回收。而這裡的幾個值是通過查詢 get_threshold()返回(700,10,10)得到的。此外,gc 模組還提供了手動回收的函式,即gc.collect()引用計數(reference counting),針對可以重複利用的記憶體緩衝區和記憶體,python使用了一種引用計數的方式來控制和判斷某快記憶體是否已經沒有再被使用。即每個物件都有一個計數器 count,記住了有多少個變數指向這個物件,當這個物件的引用計數器為 0 時,假如這個物件在緩衝區內,那麼它地址空間不會被釋放,而是等待下一次被使用,而非緩衝區的該釋放就釋放。這裡通過 sys 包中的getrefcount()來獲取當前物件有多少個引用。
22、什麼是 lambda 函式?它有什麼好處?
答:lambda 函式是一個可以接收任意多個引數(包括可選引數)並且返回單個表示式值的函式
(1)lambda 函式比較輕便,即用即仍,很適合需要完成一項功能,但是此功能只
在此一處使用,連名字都很隨意的情況下;
(2)匿名函式,一般用來給 filter,map 這樣的函數語言程式設計服務;
(3)作為回撥函式,傳遞給某些應用,比如訊息處理
23、python 是如何進行型別轉換的?
答:Python 提供了將變數或值從一種型別轉換成另一種型別的內建函式
int(x [,base ]) 將 x 轉換為一個整數
long(x [,base ]) 將 x 轉換為一個長整數
float(x ) 將 x 轉換到一個浮點數
complex(real [,imag ]) 建立一個複數
str(x ) 將物件 x 轉換為字串
repr(x ) 將物件 x 轉換為表示式字串
eval(str ) 用來計算在字串中的有效 Python 表示式,並返回一個物件
tuple(s ) 將序列 s 轉換為一個元組
list(s ) 將序列 s 轉換為一個列表
chr(x ) 將一個整數轉換為一個字元
unichr(x ) 將一個整數轉換為 Unicode 字元
ord(x ) 將一個字元轉換為它的整數值
hex(x ) 將一個整數轉換為一個十六進位制字串
oct(x ) 將一個整數轉換為一個八進位制字串
24、python 中 pass 語句的作用是什麼?
答:pass 語句什麼也不做,一般作為佔位符或者建立佔位程式,pass 語句不會執行任何操作,pass 在軟體設計階段也經常用來作為介面設計,實現相應的重寫實現
25、如何知道一個 python 物件的型別?
答:通過 type()獲取物件的型別,也可通過isinstance()去判斷物件是否是某型別
26、@(decorator)的作用是什麼?
答:裝飾器是一個很著名的設計模式,經常被用於有切面需求的場景,較為經典的有插入日誌、效能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函式中與函式功能本身無關的雷同程式碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的物件新增額外的功能
27、Python 有哪些資料結構
答:序列:列表、元祖
對映:字典
集合:set
28、io 密集型和 cpu 密集型區別
答:io 密集型:系統運作,大部分的狀況是 CPU 在等 I/O (硬碟/記憶體) 的讀/寫
Cpu 密集型:大部份時間用來做計算、邏輯判斷等 CPU 動作的程式稱之 CPU 密集型
29、Python 特殊語法:filter、map、reduce、lambda
答:
filter(...)
filter(function or None, sequence) -> list, tuple, or string
function:接受一個引數,返回布林值 True 或 False
sequence:序列可以是 str,tuple,list
filter 函式會對序列引數 sequence 中的每個元素呼叫 function 函式,最後返回的結果包含呼叫結果為 True 的元素。
map(...)
map(function, sequence[, sequence, ...]) -> list
function:是一個函式
sequence:是一個或多個序列,取決於 function 需要幾個引數,返回值是一個 list
引數序列中的每一個元素分別呼叫 function 函式,返回包含每次 function 函式返回值的 list
reduce(...)
reduce(function, sequence[, initial]) -> value
function:該函式有兩個引數
sequence:序列可以是 str,tuple,list
initial:固定初始值
reduce 依次從 sequence 中取一個元素,和上一次呼叫 function 的結果做引數再次呼叫 function。 第一次呼叫 function時,如果提供 initial 引數,會以 sequence中的第一個元素和 initial 作為引數呼叫function,否則會以序列 sequence 中的前兩個元素做引數呼叫 function。 注意 function 函式不能為 None
lambda
python lambda 會建立一個函式物件,但不會把這個函式物件賦給一個識別符號
31、談談你對面向物件的理解
答: 面向物件是相對於面向過程而言的。面向過程語言是一種基於功能分析的、以演算法為中心的程式設計方法;而面向物件是一種基於結構分析的、以資料為中心的程式設計思想。在面嚮物件語言中有一個有很重要東西,叫做類。
面向物件有三大特性:封裝、繼承、多型。
32、交換兩個變數的值
答:a,b = b,a
33、對於一個字串進行逐字元或逐詞的反轉
答:
def string_reverse(string):
return string[::-1]
34、and or 作為三目運算子時需要注意哪些事項
答:注意 and 是左右同時滿足真,or 是從左到右,只要左邊出現真就不會去判
斷後面一個條件
>>> True and 1 or 0
1
>>> False and 1 or 0
0
>>> True and "Fire" or "Water"
'Fire'
>>> False and "Fire" or "Water"
'Water'
35、對於 dict 的 items() 與 iteritems()有什麼區別
答:在 python2 中,dict.items(): 返回一個的 dictionary’s ( key,value ) 對的列表。
dict.iteritems(): 返回一個迭代器 通過dictionary’s ( key,value ) 對
>>> d={1:'one',2:'two',3:'three'}
>>> type(d.items())
<type 'list'>
>>> type(d.iteritems())
<type 'dictionary-itemiterator'>
注意:在 python3 中不存在 iteritems 屬性,只有 items 屬性,並且返回的是列表,如果需要其返回迭代器那麼,需要顯示轉換 iter(d.items())
36、如何用 python 實現單例模式
答:這只是其中的一種實現方式
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
one = MyClass()
two = MyClass()
37、有兩個 list,寫出對應組合生成一個 dict 的方法 如 name =['a','b'] age = [18,19]
答:
dict(zip(name,age))
38、寫出一個函式,給定引數 n,生成含有 n 個元素值為 1~n 的陣列,元素順序隨機,但值不重複。
答:
#encoding=utf-8
import random
def getList(n):
setlist = []
while len(setlist) < n:
num = random.randint(1,n)
if num not in setlist:
setlist.append(num)
return setlist
setlist = getList(20)
print setlist
40、設計實現遍歷目錄與子目錄,抓取.pyc 檔案
答:
import os
res = []
for root,directory,files in os.walk("./"):
print root
for filename in files:
name, suf = os.path.splitext(filename)
if suf == ".pyc":
res.append(os.path.join(root, filename))
print res
41、域名解析的過程
答:(1)現在我有一臺計算機,通過 ISP 接入了網際網路,那麼 ISP 就會給我分配一個 DNS 伺服器,這個 DNS 伺服器不是權威伺服器,而是相當於一個代理的 dns解析伺服器,他會幫你迭代權威伺服器返回的應答,然後把最終查到 IP 返回給你。
(2)現在的我計算機要向這臺 ISPDNS 發起請求查詢 www.baidu.com 這個域名了,(經網友提醒:這裡其實準確來說不是 ISPDNS,而應該是使用者自己電腦網路設定裡的 DNS,並不一定是 ISPDNS。比如也有可能你手工設定了 8.8.8.8)
(3)ISPDNS 拿到請求後,先檢查一下自己的快取中有沒有這個地址,有的話就直接返回。這個時候拿到的 ip 地址,會被標記為非權威伺服器的應答。
(4)如果快取中沒有的話,ISPDNS 會從配置檔案裡面讀取 13 個根域名伺服器的地址(這些地址是不變的,直接在 BIND 的配置檔案中),
(5)然後像其中一臺發起請求。
(6)根伺服器拿到這個請求後,知道他是 com.這個頂級域名下的,所以就會返回com 域中的 NS 記錄,一般來說是 13 臺主機名和 IP。
(7)然後 ISPDNS 向其中一臺再次發起請求,com 域的伺服器發現你這請求是baidu.com 這個域的,我一查發現了這個域的 NS,那我就返回給你,你再去查。
(8)ISPDNS 不厭其煩的再次向 baidu.com 這個域的權威伺服器發起請求,baidu.com 收到之後,查了下有 www的這臺主機,就把這個 IP 返回給你了,
(9)然後 ISPDNS 拿到了之後,將其返回給了客戶端,並且把這個儲存在快取記憶體中。
42、請寫出一段 Python 程式碼實現刪除一個 list 裡面的重複元素
答:
方法一:
ids = [1,2,3,3,4,6,6,7]
new_ids = []
for id in ids:
if id not in new_ids:
new_ids.append(id)
print new_ids
方法二:
import itertools
ids.sort()
it = itertools.groupby(ids)
new_ids5 = []
for k, g in it:
new_ids5.append(k)
print new_ids5
方法三:
new_ids3 = list(set(ids))
new_ids3.sort(ids.index)
print new_ids3
方法四:
ids = [1, 2, 3, 3, 4, 6, 6, 7]
new_ids4 = reduce(lambda x, y: x if y in x else x + [y], [[], ] + ids)
print new_ids4
43、現有一個檔案 url.txt,每一行都是一個網站名(例如:map.baidu.com)請用 Python 讀取這個檔案並且使用正則表示式匹配簡單的以“www.”開頭,以“.com”或者".edu"或者".gov"作結尾的web 域名,然後輸出到另一個檔案中
答:
#encoding=utf-8
def isDomain(line):
l = len(line)
if line.startswith("www") or line[:l-1].endswith(".com") or line[:l-1].endswith(".edu") or line[:l-1].endswith(".gov"):
return True
else:
return False
def getDomain(filename,destname):
fr = open(filename,"r+")
fw = open(destname,"w+")
file_object = fr.readlines()
for line in file_object:
print line
if isDomain(line):
fw.write(line)
fr.close()
fw.close()
return None
getDomain("source.txt","dest.txt")
44、兩個序列 a,b,大小都為 n,序列元素的值任意整形數,無序:要求:通過交換 a,b 中的元素,使[序列 a 元素的和]與[序列 b 元素的和]
之間的差最小。
答:
求解思路:
(1)求出兩個序列的差 num = sum(a) – sum(b)
(2)假如交換了 a 中的 i,下表和 b 中的 j 下表的元素,則交換後的差為:
num’ = (sum(a) – a[i] + b[j]) – (sum(b) – b[j] + a[i])
num’ = sum(a) – sum(b) – 2(a[i] - b[j])
num’ = num-2(a[i] - b[j])
(3)那麼由此我們可以得出,假設 a[i]-b[j]=x,那麼 num’ = num-2x,所以,我們去一直尋找 i 和 j,使得 x 在(0,num)之間,就將其交換,最後直到不
出這樣的 i 和 j
程式碼如下:
#encoding=utf-8
def convertMin(list1,list2):
if len(list1) != len(list2):
return
sum1 = sum(list1)
sum2 = sum(list2)
if sum1 < sum2:
list1,list2 = list2,list1
temp = True
length = len(list1)
while temp:
temp = False
for i in xrange(length):
for j in xrange(length):
print "123"
sumindex = list1[i] - list2[j]
sumall = sum(list1) - sum(list2)
if (sumindex < sumall) and (sumindex > 0):
temp = True
list1[i],list2[j] = list2[j],list1[i]
a = [3,2,5,7,5,9]
b = [1,2,3,2,6,7]
convertMin(a,b)
print "---------",
print a,b
45、什麼時候用 is 什麼時候用 ==
答:(1)== is for value equality. Use it when you would like to know if two objects have the same value.
(2)is is for reference equality. Use it when you would like to know if two references refer to the same object.
可以根據快取整型資料的範圍-5~257來理解:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
46、python 新類和舊類的區別
答:Python 2.x 中預設都是經典類,只有顯式繼承了 object 才是新式類
Python 3.x 中預設都是新式類,不必顯式的繼承 object
(1)新式類物件可以直接通過__class__屬性獲取自身型別:type,型別的統一
(2)繼承搜尋的順序發生了改變,經典類多繼承屬性搜尋順序: 先深入繼承樹左側,再返回,開始找右側;新式類多繼承屬性搜尋順序: 先水平搜尋,然後再向上移動
(3) 新式類增加了__slots__內建屬性, 可以把例項屬性的種類鎖定到__slots__規定的範圍之中
47、python 中閉包函式的理解
答:對於內部函式 g,它能引用到外部函式 f 的區域性變數 n,而且即使 f 已經返回。把這種現象就稱為閉包, 當函式 f 的生命週期結束之後,n 這個變數依然存在,因為它被閉包引用了,所以不會被回收。和閉包相關的就是 __closure__ 屬性
48、請寫出一段 Python 程式碼實現分組一個 list 裡面的元素,比如
[1,2,3,...100]變成 [[1,2,3],[4,5,6]....]
答:
[a[i:i+3] for i in xrange(0,len(a),3)]
49、用過裝飾器嗎,怎麼實現裝飾器,function 怎麼呼叫的?
答:
a) 用過, 裝飾器是一個很著名的設計模式,經常被用於有切面需求的場景,較為經典的有插入日誌、效能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函式中與函式功能本身無關的雷同程式碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的物件新增額外的功能。
b) 舉例:
import time
def timeit(func):
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper
@timeit
def foo():
print 'in foo()'
foo()
利用裝飾器 functools.wraps(func),返回裝飾器裡真的函式名
import time
import functools
def timeit(func):
@functools.wraps(func)
def wrapper():
start = time.clock()
func()
end =time.clock()
print 'used:', end - start
return wrapper
@timeit
def foo():
print 'in foo()'
foo()
print foo.__name__
首先注意第 5 行,如果註釋這一行,foo.__name__將是'wrapper'。另外相信你也注意到了,這個裝飾器竟然帶有一個引數。實際上,他還有另外兩個可選的引數,assigned 中的屬性名將使用賦值的方式替換,而 updated 中的屬性名將使用update 的方式合併,你可以通過檢視 functools 的原始碼獲得它們的預設值。對於這個裝飾器,相當於 wrapper = functools.wraps(func)(wrapper)
50、在 Python 中,類和物件有什麼區別?物件如何訪問類的方法?類(不是物件)在建立時做了什麼?
答:a) python 裡一切都是物件,例項是物件,類是物件,元類也是物件.
i. 類是物件的模板或藍圖,類是物件的抽象化,物件是類的例項化。類不代表具體的事物,而物件表示具體的事物。
ii. 類本身也是一個物件,通過使用關鍵字class建立類時,Python解析器會自動建立一個物件(物件名為類名),自身擁有建立物件(類例項)的能力,但是本質仍是一個物件可以做如下操作
(1)你可以將它賦值給一個變數
(2)你可以拷貝它
(3)你可以為它增加屬性
(4) 你可以將它作為函式引數進行傳遞
(5)執行時動態建立類,也可以通過 type(“testobj”,(object,),{})手動建立
b) 類(class)是抽象的模板, 在 python 中,一個物件的特徵也稱為屬性(attribute)。它所具有的行為也稱為方法(method)結論:物件=屬性+方法
c) 例項(instance)是是根據類創建出來的一個個具體的”物件”,每個物件都有相同的方法,但資料不同
d) 物件可以在建立類時,通過定義建構函式__init__()方法來進行初始化,例項化物件時進行傳參.
e) 元類是類的類,可以稱為類工廠, type 就是 Python 的內建元類,元類可以建立類(物件),type,str,int,都是元類可以通過__class__檢視,所有元類都是從一個類建立而來,就是 type.通過 int.__class__.__class__檢視結果<type ‘type’>
f) 物件可以通過例項化類,然後直接用.的方式呼叫類方法
51、python sentry 實時日誌
答:Sentry 是一個實時的事件日誌和聚合平臺,基於 Django 構建,其專注於錯誤監控以及提取一切事後處理所需資訊而不依賴於麻煩的使用者反饋。Sentry 可以幫助你將 Python 程式的所有 exception 自動記錄下來,然後在一個好用的 UI 上呈現和搜尋。處理 exception 是每個程式的必要部分,所以Sentry 也幾乎可以說是所有專案的必備元件,無論測試如何完善的程式,bug 總是免不了會存在的,有些 bug 不是每次都會出現,測試時執行好好的程式碼可能在某個使用者使用時就歇菜了,可是當程式在用
戶面前崩潰時,你是看不到錯誤的,當然你會說:”Hey, 我有記日誌呢”。 但是說實話,程式每天每時都在產生大量的日誌,而且分佈在各個伺服器上,並且如果你有多個服務在維護的話,日誌的數量之多你是看不過來的吧。等到某天某個使用者實在受不了了,打電話來咆哮的時候,你再去找日誌你又會發現日誌其實沒什麼用:缺少上下文,不知道使用者什麼操作導致的異常,異常太多(從不看日誌的緣故)不知如何下手 等等。
Sentry 就是來幫我們解決這個問題的,它是一款精緻的 Django 應用,目的在於幫助開發人員從散落在多個不同伺服器上毫無頭緒的日誌檔案裡發掘活躍的異常,繼而找到潛在的臭蟲。
Sentry 是一個日誌平臺, 它分為客戶端和服務端,客戶端(目前客戶端有Python, PHP,C#, Ruby 等多種語言)就嵌入在你的應用程式中間,程式出現異常就
向服務端傳送訊息,服務端將訊息記錄到資料庫中並提供一個 web 節目方便檢視。Sentry 由 python 編寫,原始碼開放,效能卓越,易於擴充套件,目前著名的使用者有 Disqus, Path, mozilla, Pinterest 等
52、說明 os,sys 不同,並舉例常用的模組用法?
答:os 與 sys 模組的不同的官方解釋:
os: This module provides a portable way of using operating system dependent functionality.
翻譯:提供一種方便的使用作業系統函式的方法。
sys:This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter.
翻譯:提供訪問由直譯器使用或維護的變數和在與直譯器互動使用到的函式。
os 常用方法
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()是否為檔案
sys 常用方法
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
因此,sys 模組區別於 os 模組,sys 模組提供了一系列的函式和變數,用於操控python 的執行時環境, 而 os 提供了訪問作業系統底層的介面.
53、deepcopy 和 copy 的區別?
答:
copy.copy 淺拷貝 只拷貝父物件,不會拷貝物件的內部的子物件。
2. copy.deepcopy 深拷貝 拷貝物件及其子物件
一個很好的例子:
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始物件
b = a #賦值,傳物件的引用
c = copy.copy(a) #物件拷貝,淺拷貝
d = copy.deepcopy(a) #物件拷貝,深拷貝
a.append(5) #修改物件 a
a[4].append('c') #修改物件 a 中的['a', 'b']陣列物件
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
輸出結果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
54、python、cython、pypy 的聯絡與區別?
答:就算是使用了 numpy 等包,再做了大量的程式碼優化工作,python 的運算速度仍然沒法令人滿意。這樣看來,python要擺脫“開發快、執行慢”這種身份還得依靠 Cython、Numba 和 Pypy,還有 llvmpy、pyston、PyCUDA 等等編譯階段的優化工具。那麼從多快省(通用性、速度、易用性)多角度出發,這些解決方案中誰才是最優秀的?
比較而言,Cython 更麻煩一點,因為你要用一種混合語言來改寫PyPy,不修改就可以直接跑程式,而且提速很大。我在現在的專案中用了 PyPy,RAM-Heavy 的程式,是 CPython 的數十倍。然後我用 Rust 重寫了一下(速度類似 Go,也接近 C++ 了),速度竟然只快了一倍……(當然現在加上多執行緒和黑科技優化以後,速度比 Python 版本快了上百倍了)Cython: 一個 Python 的超集,能夠呼叫C 語言的函式
a) 目標: 允許你為你的Python程式碼寫C擴充套件 b) 允許你為你的Python程式碼加入靜態型別,執行編譯並達到接近 C 語言的效能。 c) 這個跟 PyPy 比較類似,但不是一樣的。使用這個的時候,在提交給編譯器之前必須使用者程式碼裡面寫好 d)這些特殊程式碼。如果使用 PyPy 的話,你寫的還是普通形式的 Python 程式碼,編譯器會幫你處理一切優化的工作。
Numba: 將 JIT 加入到被註解的 Python程式碼中,簡單來講就是,你給它一些提示,它就會優化加速你這段程式碼。
Numba 是 Anaconda 發行版(一系列資料分析和管理的軟體包)的一部分。
IPython: 跟我們討論過的其他版本完全不一樣。這是一個 Python 的計算環境。為一些 GUI 工具集和瀏覽器體驗等提供支援
JIT 編譯器,英文寫作 Just-In-Time Compiler,中文意思是即時編譯器 例如, 被JIT(及時編譯)採用的通用方法:
標識被經常執行的位元組碼。
把其編譯成本地的機器碼。
快取該結果。
當同樣的的位元組碼再次被執行的時候,會取預編譯的機器碼,得到好處(例如速度提升)。
這是關於 PyPy 的用處: 把 JIT 代入 Python 語言 (參看前面成果的附錄).當然也有其他目的: PyPy 目標是成為一個
55、有沒有用過 with statement,有什麼好處?
答:用來代替傳統的 try...finally 語法的。
class Sample:
def __enter__(self):
print "In __enter__()"
return "Foo"
def __exit__(self, type, value, trace):
print "In __exit__()"
def get_sample():
return Sample()
with get_sample() as sample:
print "sample:", sample
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()
with open("/tmp/foo.txt") as file:
data = file.read()
enter()方法被執行
enter()方法返回的值 - 這個例子中是"Foo",賦值給變數'sample'
執行程式碼塊,列印變數"sample"的值為 "Foo"
exit()方法被呼叫 with 真正強大之處是它可以處理異常。可能你已經注意到
Sample 類的 exit 方法有三個引數- val, type 和 trace。這些引數在異常處理中相當有用。
56、Python 中的可變資料型別和不可變資料型別
答:不可變型別:string,integer,tuple
>>> var1 = 1
>>> var2 = var1
>>> var1,var2
(1, 1)
>>> id(var1),id(var2) #同指同一記憶體區域,id 相同
(21200672, 21200672)
>>> var1 += 1
>>> var1,var2
(2, 1)
>>> id(var1),id(var2)#由於 var1,var2 資料不可變的,對 var1+1 後,申請另外一
塊區域,id(var1)變了,id(var2)不變,對此區域 ref 數字-1
(21200660, 21200672)
>>>
可變型別:list,dict
>>> lst1 = [1,2,3]
>>> lst2 = lst1
>>> lst1,lst2
([1, 2, 3], [1, 2, 3])
>>> id(lst1),id(lst2)
(28497360, 28497360)
>>> lst1.append(4)#可變型別的,append 後,address 會保持不變
>>> lst1,lst2
([1, 2, 3, 4], [1, 2, 3, 4])
>>> id(lst1),id(lst2)#lst1,lst2 一直指向同一區域
(28497360, 28497360)