1.Python解釋器種類以及特點(diǎn)
CPython
c語(yǔ)言開發(fā)的 使用最廣的解釋器
IPython
基于cpython之上的一個(gè)交互式計(jì)時(shí)器 交互方式增強(qiáng) 功能和cpython一樣
PyPy
目標(biāo)是執(zhí)行效率 采用JIT技術(shù) 對(duì)python代碼進(jìn)行動(dòng)態(tài)編譯,提高執(zhí)行效率
JPython
運(yùn)行在Java上的解釋器 直接把python代碼編譯成Java字節(jié)碼執(zhí)行
IronPython
運(yùn)行在微軟 .NET 平臺(tái)上的解釋器,把python編譯成. NET 的字節(jié)碼
2.python的遞歸深度
遞歸深度
**Python語(yǔ)言默認(rèn)的遞歸深度是很有限的,當(dāng)遞歸深度超過值的時(shí)候,就會(huì)引發(fā)RuntimeError異常****
Python專門設(shè)置的一種機(jī)制用來防止無限遞歸造成Python溢出,這個(gè)值理論上1000,實(shí)際運(yùn)行時(shí)在900多次時(shí)就會(huì)報(bào)錯(cuò)
解決方案
最大遞歸次數(shù)是可以重新調(diào)整的。解決的方式是手工設(shè)置遞歸調(diào)用深度:
import sys
sys.setrecursionlimit(1000000) #執(zhí)行這個(gè)代碼后,遞歸深度調(diào)整到1000000層,基本上夠用了
其他辦法:改成非遞歸
3.python的深淺拷貝
定義
深拷貝的時(shí)候python將所有數(shù)據(jù)在內(nèi)存中新建了一份,所以如果你修改新的模版的時(shí)候老模版不會(huì)變。相反,在淺copy 的時(shí)候,python僅僅將最外層的內(nèi)容在內(nèi)存中新建了一份出來,第二層并沒有在內(nèi)存中新建,所以你修改了新模版,默認(rèn)模版也被修改了
下面我們先看一個(gè)具體的例子
淺拷貝
import copy
wife = {'name':{'diaoq':30},'slaras':10000}
hasband = copy.copy(wife)
print(hasband,wife)
# {'name': {'diaoq': 30}, 'slaras': 10000} {'name': {'diaoq': 30}, 'slaras': 10000}
hasband['name']['diaoq']= 32
hasband['slaras'] = 12000
print(hasband)
# {'slaras': 12000, 'name': {'diaoq': 32}}
print(wife)
# {'slaras': 12000, 'name': {'dioq': 32}}
深拷貝
import copy
wife = {'name':{'diaoq':30},'slaras':10000}
hasband = copy.deepcopy(wife)
print(hasband,wife)
# {'name': {'diaoq': 30}, 'slaras': 10000} {'name': {'diaoq': 30}, 'slaras': 10000}
hasband['name']['diaoq']= 32
hasband['slaras'] = 12000
print(hasband)
# {'slaras': 12000, 'name': {'diaoq': 32}}
print(wife)
# {'slaras': 10000, 'name': {'diaoq': 30}}
總結(jié)
- 淺拷貝時(shí),修改的元素類型是可變類型時(shí),他變我也變,修改的類型是不可變類型時(shí),他變我不變
- 深拷貝時(shí),他變我不變
4. python的匿名函數(shù)
為了解決那些功能很簡(jiǎn)單的需求而設(shè)計(jì)的一句話函數(shù)
函數(shù)名 = lambda 參數(shù) :返回值
-
匿名函數(shù)不管邏輯多復(fù)雜,只能寫一行,且邏輯執(zhí)行結(jié)束后的內(nèi)容就是返回值
temp = lambda x,y:x+y print(temp(4,10)) # 14 可以替代: def foo(x,y): return x+y print(foo(4,10)) # 14
5. 裝飾器
裝飾器(Decorators)是 Python 的一個(gè)重要部分。簡(jiǎn)單地說:他們是修改其他函數(shù)的功能的函數(shù)。他們有助于讓我們的代碼更簡(jiǎn)短,裝飾器本質(zhì)上是一個(gè)高階函數(shù),所以裝飾器也可以有自己的參數(shù)
日志裝飾器
日志是裝飾器運(yùn)用的另一個(gè)亮點(diǎn)
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
# Output: addition_func was called
wraps作用
被裝飾后的函數(shù)其實(shí)已經(jīng)是另外一個(gè)函數(shù)了(函數(shù)名等函數(shù)屬性會(huì)發(fā)生改變),所以,Python的functools包中提供了一個(gè)叫wraps的decorator來消除這樣的副作用。寫一個(gè)decorator的時(shí)候,最好在實(shí)現(xiàn)之前加上functools的wrap,它能保留原有函數(shù)的名稱和docstring
6. *args,**kwargs?參數(shù)是什么?
如果我們不確定要往函數(shù)中傳入多少個(gè)參數(shù),或者我們想往函數(shù)中以列表和元組的形式傳參數(shù)時(shí),那就使要用*args;如果我們不知道要往函數(shù)中傳入多少個(gè)關(guān)鍵詞參數(shù),或者想傳入字典的值作為關(guān)鍵詞參數(shù)時(shí),那就要使用**kwargs
7.python中的負(fù)號(hào)“-”
字符串和列表都適用
ss = "abcd"
#output: abc
#打印字符串長(zhǎng)度len(ss)-1的內(nèi)容
print(ss[:-1])
#output: dcba
#字符串反轉(zhuǎn),-1,表示依次反轉(zhuǎn)
print(ss[::-1])
#output: db
#字符串反轉(zhuǎn),-2,表示相隔一個(gè)字符反轉(zhuǎn)
print(ss[::-2])
#output: c
#字符串的倒數(shù)第二個(gè)字符
print(ss[::-2])
8. python單下劃線和雙下劃線
單下劃線
常用于模塊中,在一個(gè)模塊中以單下劃線開頭的變量和方法會(huì)被默認(rèn)劃入模塊內(nèi)部范圍。當(dāng)使用 from my_module import * 導(dǎo)入時(shí),單下劃線開頭的變量和方法是不會(huì)被導(dǎo)入的。但使用 import my_module 導(dǎo)入的話,仍然可以用 my_module._var 這樣的形式訪問屬性或方法
雙下劃線
雙下劃線開頭和結(jié)尾的是一些 python 的“魔術(shù)”對(duì)象,如類成員的 __init__、__del__、__add__、__getitem__ 等,以及全局的__file__、__name__等,多用來表示私有變量或類
9.python的內(nèi)存管理
Python的內(nèi)存管理是由私有heap空間管理的。所有的Python對(duì)象和數(shù)據(jù)結(jié)構(gòu)都在一個(gè)私有heap中。程序員沒有訪問該heap的權(quán)限,只有解釋器才能對(duì)它進(jìn)行操作。為Python的heap空間分配內(nèi)存是由Python的內(nèi)存管理模塊進(jìn)行的,其核心API會(huì)提供一些訪問該模塊的方法供程序員使用。Python有自帶的垃圾回收系統(tǒng),它回收并釋放沒有被使用的內(nèi)存,讓它們能夠被其他程序使用
10. 多進(jìn)程與多線程的區(qū)別
1. 一個(gè)程序至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程
2.線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高
3.進(jìn)程在執(zhí)行過程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率
4.線程在執(zhí)行過程中與進(jìn)程還是有區(qū)別的。每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制
5.從邏輯角度來看,多線程的意義在于一個(gè)應(yīng)用程序中,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。但操作系統(tǒng)并沒有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用,來實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。這就是進(jìn)程和線程的重要區(qū)別
11.文件操作:read,readline和readlines
read
讀取整個(gè)文件將文件內(nèi)容放到一個(gè)字符串變量中,劣勢(shì)是:如果文件非常大,尤其是大于內(nèi)存時(shí),無法使用read()方法
readline
每次讀取一行;返回的是一個(gè)字符串對(duì)象,保持當(dāng)前行的內(nèi)存,缺點(diǎn):比readlines慢得多
readlines
一次性讀取整個(gè)文件;自動(dòng)將文件內(nèi)容分析成一個(gè)行的列表
12.如何判斷單向鏈表中是否有壞
首先遍歷鏈表,尋找是否有相同地址,借此判斷鏈表中是否有環(huán)。如果程序進(jìn)入死循環(huán),則需要一塊空間來存儲(chǔ)指針,遍歷新指針時(shí)將其和儲(chǔ)存的舊指針比對(duì),若有相同指針,則該鏈表有環(huán),否則將這個(gè)新指針存下來后繼續(xù)往下讀取,直到遇見NULL,這說明這個(gè)鏈表無環(huán)
13.sort和sorted的區(qū)別
1.sorted執(zhí)行之后返回一個(gè)新的列表,sort是在原有的列表做修改
2. sorted 可以對(duì)更多組合排序,sort只能對(duì)列表排序
list1 = [1,3,2,6,4]
list1.sort()
print(list1)# [1,2,3,4,6]
d = {1: 1000, 4: 250, 2: 750, 3: 500}
d2 = sorted(d.items())
print(d2) # [(1, 1000), (2, 750), (3, 500), (4, 250)]
可以看到,sorted可以對(duì)元祖進(jìn)行排序
14. 列表解析式
列表解析式又叫列表推導(dǎo)式,和標(biāo)準(zhǔn)的python循環(huán)相比,不僅可讀性強(qiáng),而且需要的代碼量也是最少的,執(zhí)行速度也是比標(biāo)準(zhǔn)循環(huán)快樂不少,對(duì)于列表推導(dǎo)式,我們可以從列表中選擇具體的元素,并做一些操作和判斷,從而創(chuàng)建新的列表。值得注意的是,我們甚至能使用 Pandas Series 或 NumPy Array 進(jìn)行列表推導(dǎo)操作,廢話不多說,直接上代碼
#標(biāo)準(zhǔn)的循環(huán)模式
list1 = [1,3,2,6,4]
list2 = []
for one in list1:
list2.append(one)
#列表推導(dǎo)式
list1 = [1,3,2,6,4]
list2 = [one for one in list1]
代碼量明顯降低了很多,當(dāng)然也可以在里面加入一些條件處理語(yǔ)句
#標(biāo)準(zhǔn)的循環(huán)模式
list1 = [1,3,2,6,4]
list2 = []
for one in list1:
if one > 2:
list2.append(one)
#列表推導(dǎo)式
list1 = [1,3,2,6,4]
list2 = [one for one in list1 if one > 2]
從代碼量上,很明顯列表推導(dǎo)式簡(jiǎn)潔了很多,只要用習(xí)慣了列表推導(dǎo)式就沒必要再去使用python標(biāo)準(zhǔn)循環(huán)