年薪百萬的python大佬竟然有空整理基礎知識,我趕緊拷貝過來分享
1:為什麼學習Python?
語言本身簡潔,優美,功能超級強大,跨平臺,桌面應用,web開發,自動化測試運維,爬蟲,人工智慧,大資料處理。本人是從Python爬蟲開始學的。
學習Python中有不明白推薦加入交流群
號:960410445
群裡有志同道合的小夥伴,互幫互助,
群裡有不錯的視訊學習教程和PDF!
2:Python和Java、PHP、C、C#、C++等其他語言的對比?
Java 程式語言是個簡單、面向物件、分散式、解釋性、健壯、安全與系統無關、可移植、高效能、多執行緒和動態的語言。
php語法吸收了C語言、Java和Perl的特點,入門門檻較低,易於學習,使用廣泛,主要適用於Web開發領域。
C#是微軟公司釋出的一種面向物件的、運行於.NET Framework之上的高階程式設計語言。
C語言,它既有高階語言的特點,又具有組合語言的特點,它是結構式語言。
python語言,是一種面向物件,直譯式計算機程式設計語言,Python語法簡潔而清晰,具有豐富和強大的類庫。
3:簡述解釋型和編譯型程式語言?
解釋型語言編寫的程式不需要執行,邊執行一行,邊翻譯一次,效率一般較低。
編譯型語言就是先編譯,將程式編譯成機器語言,然後執行程式,一般而言程式效率較高。
4:Python直譯器種類以及特點?
CPython 從Python官網下載並且安裝完後Python相應的直譯器為CPython直譯器。
IPython IPython是基於CPython之上的一個互動式直譯器,好比國產瀏覽器外觀不一樣,核心就是呼叫的IE。
PyPy PyPy採用JIT技術,對Python程式碼進行動態編譯,所以可以顯著提高Python程式碼的執行速度。
Jython Jython是執行在Java平臺上的Python直譯器,可以直接把Python程式碼編譯成Java位元組碼執行
IronPython IronPython和Jython類似,只不過IronPython是執行在微軟.Net平臺上的Python直譯器,可以直接把Python程式碼編譯成.Net的位元組碼。
在Python的直譯器中,使用廣泛的是CPython。
5:位和位元組的關係?
位:"位(bit)"是電子計算機中最小的資料單位。每一位的狀態只能是0或1。8個二進位制位構成1個"位元組(Byte)",它是儲存空間的基本計量單位。1個位元組可以儲存1個英文字母或者半個漢字,換句話說,1個漢字佔據2個位元組的儲存空間。
字:"字"由若干個位元組構成,字的位數叫做字長,不同檔次的機器有不同的字長。例如一臺8位機,它的1個字就等於1個位元組,字長為8位。如果是一臺16位機,那麼,它的1個字就由2個位元組構成,字長為16位。字是計算機進行資料處理和運算的單位。
6:b、B、KB、MB、GB 的關係?
計算機儲存資訊的大小,最基本的單位是位元組,一個漢字由兩個位元組組成,字母和數字由一個位元組組成。 容量的單位從小到大依次是:位元組(B)、KB、MB、GB、TB。它們之間的關係是
1TB=1024GB
1GB=1024MB
1MB=1024KB
1KB=1024B
7:請至少列舉5個PEP8規範(越多越好)。
具體詳情參見Python PEP8規範官網 https://legacy.python.org/dev/peps/pep-0008/
主要分為以下幾類 程式碼編排 文件編排 空格的使用 註釋 文件描述 命名規則 程式設計建議
第一,其中程式設計建議暫時舉例如下:
No1:推薦使用 .join() 而不使用+ 。
No2:儘可能使用is is not 取代‘==’,‘!=’,比如if x is not None要優於if x。
No3:使用基於類的異常,每個模組或包都有自己的異常類,此異常類繼承自Exception。
No4:異常中不要使用裸露的except,except後跟具體的exceptions。
No5:異常中try的程式碼儘可能少。
No6:使用startswith() and endswith()代替切片進行序列字首或字尾的檢查。
No7:使用isinstance()比較物件的型別。
No8:判斷序列空或不空。
第二,其中命名建議如下:
No1:模組命名儘量短小,使用全部小寫的方式,可以使用下劃線。
No2:包命名儘量短小,使用全部小寫的方式,不可以使用下劃線。
No3:類的命名使用CapWords的方式,模組內部使用的類採用_CapWords的方式。
No4:異常命名使用CapWords+Error字尾的方式。
No5:全域性變數儘量只在模組內有效,類似C語言中的static。實現方法有兩種,一是all機制,二是字首一個下劃線。
No6:函式命名使用全部小寫的方式,可以使用下劃線。
No7:常量命名使用全部大寫的方式,可以使用下劃線。
No8:類的屬性(方法和變數)命名使用全部小寫的方式,可以使用下劃線。
No9:類的屬性有3種作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public屬性前,字首一條下劃線。
No10:類的屬性若與關鍵字名字衝突,字尾一下劃線,儘量不要使用縮略等其他方式。
No11:為避免與子類屬性命名衝突,在類的一些屬性前,字首兩條下劃線。比如:類Foo中宣告__a,No1:訪問時,只能通過Foo__a,避免歧義。如果子類也叫Foo,那就無能為力了。
No12:類的方法第一個引數必須是self,而靜態方法第一個引數必須是cls。
第三,其中Python常用技巧如下:
使用 Counter 進行計數統計。
enumerate獲取鍵值對。
os.path.join用於拼接路徑,好處是可以根據系統自動選擇正確的路徑分隔符”/”或””。
os.path.split 把路徑分割成dirname和basename,返回一個元組。
os.listdir 獲取路徑下所有檔案,返回list。
os.getcwd()獲取檔案的當前路徑。
列表推導式 如 [i for i in range(10]。
對於輕量級迴圈,可儘量使用列表推導式,熟練使用列表推導式可以很多情況下代替map,filter等操作。
函式呼叫裡的*arg和**kwarg。
chr() frozenset() list()range()vars()等內建函式 。
列印輸出函式帶有顏色如下:
print("[32;1m找的數在mid[%s]右面[0m" % data_set[mid])。
sys.getfilesystemencoding() #返回將Unicode檔名轉換成系統檔名的編碼的名字。
os.makedirs('dir1/dir2') 可生成多層遞迴目錄。
儘管 classmethod 和 staticmethod 非常相似,但在用法上依然有一些明顯的區別。classmethod 必須有一個指向類物件的引用作為第一個引數,而 staticmethod 可以沒有任何引數。
第四,python常用功能:
python的四個重要內建函式:getattr、hasattr、delattr和setattr較為全面的實現了基於字串的反射機制。他們都是對記憶體內的模組進行操作,並不會對原始檔進行修改。
8:isinstance作用?isinstance作用以及應用場景?
isinstance 用來判斷一個物件是否是一個已知的型別。
9:什麼是面向物件的mro?
解析類繼承的查詢順序 MRO:Method Resolution Order,即方法解析順序,是python中用於處理二義性問題的演算法 。
10:Python的作用域?
本地作用域(Local)→當前作用域被嵌入的本地作用域(Enclosing locals)→全域性/模組作用域(Global)→內建作用域(Built-in)
11:裝飾器的寫法以及應用場景。
我們回到日誌的例子 並建立一個包裹函式,能讓我們指定一個用於輸出的日誌檔案。
在函式中嵌入裝飾器 帶引數的裝飾器是典型的閉包函式。
裝飾器能有助於檢查某個人是否被授權去使用一個web應用的端點(endpoint)。它們被大量使用於Flask和Django web框架中。
12:用盡量多的方法實現單例模式。
執行元類的__new__方法和__init__方法用來例項化類物件,__call__ 方法用來對例項化的物件的例項即類的物件進行控制。__call__方法會呼叫例項類的 __new__方法,用於建立物件。返回物件給__call__方法,然後呼叫類物件的 __init__方法,用於對物件初始化。
利用類的靜態方法或者類方法,實現對函式初始化的控制。該方法需要手動呼叫靜態方法實現例項。本質上是手動版的__new__方法。
先執行了類的__new__方法(我們沒寫時,預設呼叫object.__new__),例項化物件;然後再執行類的__init__方法,對這個物件進行初始化,所有我們可以基於這個,實現單例模式。
靜態變數方法:
Python 的模組就是天然的單例模式,因為模組在第一次匯入時,會生成 .pyc 檔案,當第二次匯入時,就會直接載入 .pyc 檔案,而不會再次執行模組程式碼。
def singleton(cls, *args, **kw): instance = {} def _singleton(args): if cls not in instance: instance[cls] = cls(*args, **kw) return instance[cls] return _singleton @singleton class A: pass
裝飾器
class Singleton1(type): def __init__(self, *args, **kwargs): self.__instance = None super(Singleton1,self).__init__(*args, **kwargs) def __call__(self, *args, **kwargs): if self.__instance is None: self.__instance = super(Singleton1,self).__call__(*args, **kwargs) return self.__instance
class Singleton2(type): _inst = {} def __call__(cls, *args, **kwargs): print(cls) if cls not in cls._inst: cls._inst[cls] = super(Singleton2, cls).__call__(*args) return cls._inst[cls] class C(metaclass=Singleton1): pass
class Singleton(object): def __new__(cls,a): if not hasattr(cls, '_instance'): cls._instance = object.__new__(cls) return cls._instance def __init__(self,a): self.a = a def aa(self): print(self.a) a = Singleton("a")
13:metaclass作用?以及應用場景?
為了當建立類使能夠自動地改變類。通常會為API做這樣的事情,希望可以建立符合當前上下文的類。
用來指定指定某個類是由哪個類建立的
14:什麼是反射?以及應用場景?
python有兩個內建函式exec和eval,他們同樣能夠執行字串。反射它的核心本質其實就是利用字串的形式去物件(模組)中操作(查詢/獲取/刪除/新增)成員,一種基於字串的事件驅動!
15:1、2、3、4、5 能組成多少個互不相同且無重複的三位數?
combinations_with_replacement 組合,有重複 (有放回抽樣組合)
combinations 組合,沒有重複 (不放回抽樣組合)
permutations 排列 (不放回抽樣排列)
product 笛卡爾積 (有放回抽樣排列)
使用python內建的排列組合函式(不放回抽樣排列)
組成後的數值不相同,且組合的三個位數之間數字不重複。
60個
16:建立類有兩種方式?
特殊方式(基於元類的方式)
普通方式
17:列舉面向物件中的特殊成員以及應用場景?
__getitem__ 、 __setitem__ 、__delitem__ 用於索引操作,如字典。分別表示獲取、設定、刪除資料__str__ 如果一個類中定義了__str__方法,那麼在列印物件時,預設輸出該方法的返回值 __dict__ 檢視類或物件中的所有成員 __call__ 物件後面加括號,觸發執行__doc__ 描述類的資訊
18:靜態方法和類方法區別?
三種方法從不同層次上來對方法進行了描述:例項方法針對的是例項,類方法針對的是類,他們都可以繼承和重新定義,而靜態方法則不能繼承,可以認為是全域性函式。。
例項方法,類方法,靜態方法都可以通過例項或者類呼叫,只不過例項方法通過類呼叫時需要傳遞例項的引用(python 3可以傳遞任意物件,其他版本會報錯)。
19:如何判斷是函式還是方法?
看他的呼叫者是誰,如果是類,需要傳入一個引數self的值,這時他就是一個函式,如果呼叫者是物件,不需要給self傳入引數值,這時他是一個方法。
20:列舉面向物件中帶爽下劃線的特殊方法?
當建立一個新例項時呼叫__new__,初始化一個例項時用__init__。只有在__new__返回一個cls的例項時後面的__init__才能被呼叫。__new__方法會返回一個建立的例項,而__init__什麼都不返回。
__new__是一個靜態方法,而__init__是一個例項方法.
__call__ __doc__ __class__ __del__ __dict__ __str__
__init__
__new__
21:是否使用過functools中的函式?其作用是什麼?
用於裝飾器中,functools.wraps(),主要是用來修復裝飾器。實際上固定了int()函式的關鍵字引數base 如 int2 = functools.partial(int, base=2)。
最後,建立偏函式時,實際上可以接收函式物件 *args和**kwargs這3個引數。
簡單總結functools.partial的作用就是,把一個函式的某些引數給固定住(也就是設定預設值),返回一個新的函式,呼叫這個新函式會更簡單。
python 中提供一種用於對函式固定屬性的函式(與數學上的偏函式不一樣)。
functools用於高階函式:指那些作用於函式或者返回其他函式的函式。通常情況下,只要是可以被當做函式呼叫的物件就是這個模組的目標。
22:面向物件中super的作用?
在super機制裡可以保證公共父類僅被執行一次,至於執行的順序,是按照MRO(Method Resolution Order),方法解析順序進行的。MRO 就是類的方法解析順序表, 其實也就是繼承父類方法時的順序表。
super 是用來解決多重繼承問題的,直接用類名呼叫父類方法在使用單繼承的時候沒問題,但是如果使用多繼承,會涉及到查詢順序(MRO)、重複呼叫(鑽石繼承)等種種問題。
super() 函式是用於呼叫父類(超類)的一個方法。
23:面向物件深度優先和廣度優先是什麼?
深度優先:不全部保留節點,佔用空間小,有回溯操作(即有入棧/出棧操作),執行速度慢。
廣度優先:保留全部節點,佔用空間大;無回溯操作(既無入棧、出棧操作)、執行速度快。
24:Python面向物件中的繼承有什麼特點?
在繼承中基類的構造(__init__()方法)不會被自動呼叫,它需要在其派生類的構造中親自專門呼叫。有別於C#。
新類經常是基於已經存在的類,這樣就可以提升程式碼的複用程度。
建造系統中的類,避免重複操作。
繼承有點類似與我們生物學上的遺傳,就是子類的一些特徵是來源於父類的,兒子遺傳了父親或母親的一些性格,或者相貌,又或者是運動天賦。有點種瓜得瓜種豆得豆的意思。面向物件裡的繼承也就是父類的相關的屬性,可以被子類重複使用,子類不必再在自己的類裡面重新定義一回,父類裡有點我們只要拿過來用就好了。而對於自己類裡面需要用到的新的屬性和方法,子類就可以自己來擴充套件了。
25: 什麼是過載?
過載就是類裡面相同方法名,不同形參的情況,可以是形參型別不同或者形參個數不同,或者形參順序不同,但是不能使返回值型別不同。
26:什麼是重寫?
重寫很簡單就是把子類從父親類裡繼承下來的方法重新寫一遍,這樣,父類裡相同的方法就被覆蓋了,當然啦,你還是可以通過super.CaculSalary方法來呼叫父類的工資計算方法。
27:什麼是多型?
我們在有一些方法在父類已經定義好了,但是子類我們自己再用的時候,發現,其實,我們的雖然都是計算工資的,但是普通員工的工資計算方法跟經理的計算方法是不一樣的,所以這個時候,我們就不能直接呼叫父類的這個計算工資的方法了。這個時候我們就需要用到面向物件的另一個特性,多型。我們要在子類裡面把父類裡面定義計算工資的方法在子類裡面重新實現一遍。多型包含了過載和重寫。
28:談談你對面向物件的理解?
所謂的面向物件就是將我們的程式模組化,物件化,把具體事物的特性屬性和通過這些屬性來實現一些動作的具體方法放到一個類裡面,這就是封裝。封裝是我們所說的面相物件程式設計的特徵之一。除此之外還有繼承和多型。
29:如何使用python刪除一個檔案?
import shutil shutil.rmtree()。
os.rmdir(path)刪除目錄 path,要求path必須是個空目錄。
os.removedirs(path) 遞迴地刪除目錄。
os.remove(path)刪除檔案 path
30:如何生成一個隨機數?
random.uniform(a,b):返回指定範圍內的浮點數。
隨機實數:random.random( ):返回0到1之間的浮點數
random.randrange(start,stop,[,step]):返回一個範圍在(start,stop,step)之間的隨機整數,不包括結束值。
隨機整數:random.randint(a,b):返回隨機整數x,a<=x<=b
31:os和sys模組的作用?
os.chmod('pathfile',os.W_OK) 改變檔案許可權模式。
os.access('pathfile',os.W_OK) 檢驗檔案許可權模式,輸出True,False。
os.path.expandvars(path) #根據環境變數的值替換path中包含的”$name”和”${name}”。
os.path.expanduser(path) #把path中包含的"~"和"~user"轉換成使用者目錄。
os.path.commonprefix(list) #返回list(多個路徑)中,所有path共有的最長的路徑。
os.path.getmtime(path) 返回path所指向的檔案或者目錄的最後修改時間。
os.path.getatime(path) 返回path所指向的檔案或者目錄的最後存取時間。
os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑之前的引數將被忽略。
os.path.isdir(path) 如果path是一個存在的目錄,則返回True。否則返回False。
os.path.isfile(path) 如果path是一個存在的檔案,返回True。否則返回False。
os.path.isabs(path) 如果path是絕對路徑,返回True。
os.path.lexists #路徑存在則返回True,路徑損壞也返回True。
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False。
os.path.basename(path) 返回path最後的檔名。如何path以/或結尾,那麼就會返回空值。即os.path.split(path)的第二個元素。
os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素。
os.path.split(path) 將path分割成目錄和檔名二元組返回。
os.path.abspath(path) 返回path規範化的絕對路徑。
os.environ 獲取系統環境變數。
os.system(bash command) 執行shell命令,直接顯示。
os.name 字串指示當前使用平臺。win->'nt'; Linux->'posix'。
os.pathsep 用於分割檔案路徑的字串。
os.linesep 當前平臺使用的行終止符,win下為 ,Linux下為 。
os.sep 作業系統特定的路徑分隔符,win下為,Linux下為/。
os.stat('path/filename') 獲取檔案/目錄資訊。
os.rename(oldname,new) 重新命名檔案/目錄。
os.remove() 刪除一個檔案。
os.listdir('dirname') 列出指定目錄下的所有檔案和子目錄,包括隱藏檔案,並以列表方式列印。
os.rmdir('dirname') 刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir 。
os.mkdir('dirname') 生成單級目錄;相當於shell中mkdir dirname。
os.removedirs('dirname1') 若目錄為空,則刪除,並遞迴到上一級目錄,如若也為空,則刪除,依此類推。
os.pardir 獲取當前目錄的父目錄字串名:('..')。
os.curdir 返回當前目錄: ('.')。
os.chdir(dirname) 改變當前指令碼工作目錄;相當於shell下cd。
os.getcwd() 獲取當前工作目錄,即當前python指令碼工作的目錄路徑。
sys模組
sys.displayhook(value) #如果value非空,這個函式會把他輸出到sys.stdout(詳細使用參考文件)
sys.setdefaultencoding(name) #用來設定當前預設的字元編碼(詳細使用參考文件)
sys.stdin.readline() #從標準輸入讀一行,sys.stdout.write(a) 螢幕輸出a
sys.getwindowsversion() #獲取Windows的版本
sys.executable #Python解釋程式路徑
sys.builtin_module_names #Python直譯器匯入的內建模組列表
sys.getdefaultencoding() #返回當前你所用的預設的字元編碼格式
sys.version_info #'final'表示最終,也有'candidate'表示候選,表示版本級別,是否有後繼的發行
sys.api_version #直譯器的C的API版本
sys.byteorder #本地位元組規則的指示器,big-endian平臺的值是'big',little-endian平臺的值是'little'
sys.exec_prefix #返回平臺獨立的python檔案安裝的位置
sys.exc_clear() #用來清除當前執行緒所出現的當前的或最近的錯誤資訊
sys.stdin.read() #輸入一行
sys.stdin #標準輸入
sys.stdout.writelines() #無換行輸出
sys.stdout.write('aaa') #標準輸出內容
sys.stdout #標準輸出
sys.maxint # 最大的Int值
sys.platform #返回作業系統平臺名稱
sys.version #獲取Python解釋程式的版本資訊
sys.hexversion #獲取Python解釋程式的版本值,16進位制格式如:0x020403F0
sys.exit(n) #退出程式,正常退出時exit(0)
sys.exc_info() #獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細資訊
sys.modules #返回系統匯入的模組欄位,key是模組名,value是模組
sys.modules.keys() #返回所有已經匯入的模組列表
sys.path #返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值
sys.argv #命令列引數List,第一個元素是程式本身路徑
sys模組主要是用於提供對python直譯器相關的操作
32:談談你對閉包的理解?
一般情況下,在我們認知當中,如果一個函式結束,函式的內部所有東西都會釋放掉,還給記憶體,區域性變數都會消失。但是閉包是一種特殊情況,如果外函式在結束的時候發現有自己的臨時變數將來會在內部函式中用到,就把這個臨時變數繫結給了內部函式,然後自己再結束。
在一個外函式中定義了一個內函式,內函式裡運用了外函式的臨時變數,並且外函式的返回值是內函式的引用。這樣就構成了一個閉包。
33:用Python實現一個二分查詢的函式。
def binary_search(data_set, data):
data_set_len = len(data_set)
if data_set_len > 1:
mid = int(data_set_len / 2)
if data_set[mid] == data: # find it
print("找到數字", data_set[mid])
elif data_set[mid] > data: # 找的數在mid左面
print("[31;1m找的數在mid[%s]左面[0m" % data_set[mid])
return binary_search(data_set[0:mid], data)
else: # 找的數在mid右面
print("[32;1m找的數在mid[%s]右面[0m" % data_set[mid])
return binary_search(data_set[mid + 1:], data)
else:
if data_set_len[0] == data:
print("找到數字啦", data_set[0])
else:
print("沒的分了,要找的數字[%s]不在列表裡" % data)
34:簡述 生成器、迭代器、可迭代物件 以及應用場景?
有__iter__和__next__方法的物件就是一個迭代器,但是迭代器不一定是生成器。
生成器:有yield關鍵字的函式就是一個生成器,生成器一定是一個迭代器
生成器:帶有yield的函式不再是一個普通函式,而是一個生成器。當函式被呼叫時,返回一個生成器物件。不像一般函式在生成值後退出,生成器函式在生成值後會自動掛起並暫停他們的執行狀態。
迭代器:是訪問集合元素的一種方式,從集合的第一個元素開始訪問,直到所有元素被訪問結束。其優點是不需要事先準備好整個迭代過程中的所有元素,僅在迭代到某個元素時才開始計算該元素。適合遍歷比較巨大的集合。__iter__():方法返回迭代器本身, __next__():方法用於返回容器中下一個元素或資料。
35:常用字串格式化哪幾種?
print('hello {first} and {second}'.format(first='df',second='another df'))
print('hello %(first)s and %(second)s'%{'first':'df' , 'second':'another df'})
print('hello %s and %s'%('df','another df'))
36:請用程式碼簡答實現stack Queue。
37:logging模組的作用?以及應用場景?
簡單來講就是,我們通過記錄和分析日誌可以瞭解一個系統或軟體程式執行情況是否正常,也可以在應用程式出現故障時快速定位問題。比如,做運維的同學,在接收到報警或各種問題反饋後,進行問題排查時通常都會先去看各種日誌,大部分問題都可以在日誌中找到答案。再比如,做開發的同學,可以通過IDE控制檯上輸出的各種日誌進行程式除錯。對於運維老司機或者有經驗的開發人員,可以快速的通過日誌定位到問題的根源。可見,日誌的重要性不可小覷通過log的分析,可以方便使用者瞭解系統或軟體、應用的執行情況;如果你的應用log足夠豐富,也可以分析以往使用者的操作行為、型別喜好、地域分佈或其他更多資訊;如果一個應用的log同時也分了多個級別,那麼可以很輕易地分析得到該應用的健康狀況,及時發現問題並快速定位、解決問題,補救損失。
軟體程式執行故障分析與問題定位
程式除錯
38:日誌級別的種類。
CRITICAL 當發生嚴重錯誤,導致應用程式不能繼續執行時記錄的資訊
ERROR 由於一個更嚴重的問題導致某些功能不能正常執行時記錄的資訊
WARNING 當某些不期望的事情發生時記錄的資訊(如,磁碟可用空間較低),但是此時應用程式還是正常執行的
INFO 資訊詳細程度僅次於DEBUG,通常只記錄關鍵節點資訊,用於確認一切都是按照我們預期的那樣進行工作
DEBUG 最詳細的日誌資訊,典型應用場景是 問題診斷
39:如何在函式中設定一個全域性變數 ?
在函式的內部,通過global宣告,使在函式內部中設定一個全域性變數,這個全域性變數可以在任意的函式中進行呼叫。
40:一行程式碼實現刪除列表中重複的值 ?
print(sorted(set(list(列表)),key=list(列表).index)) # sorted output
41:如何用一行程式碼生成[1,4,9,16,25,36,49,64,81,100] ?
a = [pow(i,2) for i in range(1,11)]
42:比較a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 b = [(1,),(2,),(3,) ] 的區別?
print([1, 2, 3]) [1, 2, 3]
print([(1), (2), (3)]) [1, 2, 3]
print((1,), (2,), (3,)) (1,) (2,) (3,)
a 列表裡面的的每個元素都是數字型別,
b 列表裡面的元素也是數字,這裡面的小括號代表的優先運算子,
c 列表裡面的每個元素都是元組。
43:如何實現[‘1’,’2’,’3’]變成[1,2,3] ?
第一種:a = [int(i) for i in a]
第二種:b = map(int, a)
44:如何實現 “1,2,3” 變成 [‘1’,’2’,’3’] ?
a = '1,2,3'.split(',')
45:def func(a,b=[]) 這種寫法有什麼坑?
函式陷阱,列表是一個可變型別,可以在任何的地方修改他那裡面的資料。
46:求結果 。
1 or 2 1
1 and 2 2
1 < (2==2) False
1 < 2 == 2 True
47:求結果。
[ i % 2 for i in range(10) ] [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]。
( i % 2 for i in range(10) ) <generator object <genexpr> at 0x000000000C0EA938>。
48:什麼是正則的貪婪匹配?
區別重點在:.* 和 .*?。
非貪婪格式:xx.*?xx 。
貪婪格式:xx.*xx 是嘗試匹配儘可能少的字元。
49:re的match和search區別?
search:從字元的起始位置開始匹配,匹配到第一個符合的就不會去匹配了。
match:嘗試從字串起始位置開始匹配如果沒有就會返回None。
50:至少列舉8個常用模組都有那些?
re,os,random,json,time,numpy,opencv-python,pytz,pyMysql,pygame,pillow-python,pip,Django
51:如何安裝第三方模組?以及用過哪些第三方模組?
在cmd終端可以使用pip install 安裝第三方模組。
可以在pycharm裡面的settings裡面手動的新增第三方模組。
現在,讓我們來安裝一個第三方庫——Python Imaging Library,這是Python下非常強大的處理影象的工具庫。一般來說,第三方庫都會在Python官方的pypi.python.org網站註冊,要安裝一個第三方庫,必須先知道該庫的名稱,可以在官網或者pypi上搜索,比如Python Imaging Library的名稱叫PIL在命令提示符視窗下嘗試執行pip,如果Windows提示未找到命令,可以重新執行安裝程式新增pip。如果你正在使用Windows,確保安裝時勾選了pip和Add python.exe to Path。如果你正在使用Mac或Linux,安裝pip本身這個步驟就可以跳過了。在Python中,安裝第三方模組,是通過setuptools這個工具完成的。Python有兩個封裝了setuptools的包管理工具:easy_install和pip。目前官方推薦使用pip
52:一行程式碼實現9*9乘法表?
print(' '.join([' '.join(['%s*%s=%-2s' % (y,x,x*y) for y in range(1,1+x)]) for x in range(1,10)]))
53:filter、map、reduce的作用?
filter是篩選出其中滿足某個條件的那些資料,字面意思是過濾,比如挑出列表中所有奇數。
reduce是用某種方法依次把所有資料丟進去最後得到一個結果,字面意思是化簡,比如計算一個列表所有數的和的過程,就是維持一個部分和然後依次把每個數加進去。
map是用同樣方法把所有資料都改成別的,字面意思是對映,比如把列表的每個數都換成其平方。
54:對給定的List L進行排序,對List、Dict進行排序,Python提供了兩個方法。
用List的成員函式sort進行排序,在本地進行排序,不返回副本。
用built-in函式sorted進行排序(從2.4開始),返回副本,原始輸入不變
Python中的map函式應用於每一個可迭代的項,返回的是一個結果list。如果有其他的可迭代引數傳進來,map函式則會把每一個引數都以相應的處理函式進行迭代處理。map()函式接收兩個引數,一個是函式,一個是序列,map將傳入的函式依次作用到序列的每個元素,並把結果作為新的list返回。
filter()函式接收一個函式 f 和一個list,這個函式 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。
55:列舉常見的內建函式?
資料集合:len,sorted,enumerate,all,any,zip,filter,map
資料集合——字典和集合:dict,set,frozenset
序列:reversed,slice
序列——字串相關的:str,format,bytes,bytearry,memoryview,ord,chr,ascii,repr
序列——列表和元組相關的:list和tuple
數字——數學運算:abs,divmod,min,max,sum,round,pow
數字——進位制轉換相關:bin,oct,hex
數字——資料型別相關:bool,int,float,complex
dir() 預設檢視全域性空間內的屬性,也接受一個引數,檢視這個引數內的方法或變數
callable(o),o是引數,看這個變數是不是可呼叫。
幫助方法(help)
__import__匯入一個模組
open() 開啟一個檔案,返回一個檔案操作符(檔案控制代碼)
hash(o) o是引數,返回一個可hash變數的雜湊值,不可hash的變數被hash之後會報錯
id(o) o是引數,返回一個變數的記憶體地址
type(o) 返回變數o的資料型別
print() 輸出
input() 輸入
locals()——獲取執行本方法所在名稱空間內的區域性變數的字典
globals()——獲取全域性變數的字典
delattr()hash()memoryview()set()
complex()hasattr()max()round()
compile()globals()map()reversed()__import__()
classmethod()getattr()locals()repr()zip()
callable()format()len() property()type()
bytes()float()iter() print()tuple()
bytearray()filter()issubclass()pow()super()
bool()exec()isinstance()ord()sum()
bin() eval()int() open() str()
ascii()enumerate()input()oct() staticmethod()
any()divmod() id() object() sorted()
all() dir() hex()next()slice()
abs()dict()help()min()setattr()
56:求
v = dict.fromkeys(['k1', 'k2'], [33])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)
{'k1': [33, 666], 'k2': [33, 666]}
{'k1': 777, 'k2': [33, 666]}
v = dict.fromkeys(['k1', 'k2'], [])
print(v)
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)
{'k1': [], 'k2': []}
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}
57:Python的可變型別和不可變型別?
對於不可變型別,無論建立多少個不可變型別,只要值相同,都指向同個記憶體地址(若值不同,那麼一定指向不同的記憶體地址)。
對於可變型別,無論建立多少個可變型別,只要值相同,都不指向同個記憶體地址(除非進行復制操作,那麼他們將會指向同一個地址)。
修改程式碼宣告兩個相同值的浮點型變數,檢視它們的id,發現它們並不是指向同個記憶體地址,這點和int型別不同(這方面涉及Python記憶體管理機制,Python對int型別和較短的字串進行了快取,無論宣告多少個值相同的變數,實際上都指向同個記憶體地址。)
對於不可變型別int,無論建立多少個不可變型別,只要值相同,都指向同個記憶體地址。同樣情況的還有比較短的字串。
對不可變型別的變數重新賦值,實際上是重新建立一個不可變型別的物件,並將原來的變數重新指向新建立的物件(如果沒有其他變數引用原有物件的話(即引用計數為0),原有物件就會被回收)。
不可變:數字、字串、元祖
可變:列表、字典
Python的每個物件都分為可變和不可變
58:Python垃圾回收機制?
分代收集:Python把記憶體根據物件存活時間劃分為三代,物件建立之後,垃圾回收器會分配它們所屬的代。每個物件都會被分配一個代,而被分配更年輕的代是被優先處理的,因此越晚建立的物件越容易被回收。連在一起,構成一個有向圖,物件構成這個有向圖的節點,而引用關係構成這個有向圖的邊)。
標記-清除:一些容器物件,比如list、dict、tuple,instance等可能會出現引用迴圈,對於這些迴圈,垃圾回收器會定時回收這些迴圈(物件之間通過引用(指標)。
引用計數:Python在記憶體中儲存每個物件的引用計數,如果計數變成0,該物件就會消失,分配給該物件的記憶體就會釋放出來。
Python中的垃圾回收是以引用計數為主,標記-清除和分代收集為輔。
59:簡述Python的深淺拷貝以及應用場景?
淺拷貝指僅僅拷貝資料集合的第一層資料,深拷貝指拷貝資料集合的所有層。所以對於只有一層的資料集合來說深淺拷貝的意義是一樣的,比如字串,數字,還有僅僅一層的字典、列表、元祖等。
深拷貝:copy.deepcopy淺拷貝:copy.copy
匯入模組:import copy
60:is和==的區別。
is是對比地址,==是對比值。
61:*arg和**kwarg作用。
接收引數。
函式定義時傳的*arg /**kwarg。
分割引數**kwarg,字典“出沒”。
*arg:元組或列表“出現”。
62:pass的作用?
保證語義完整
保證格式完整
空語句 do nothing
63:lambda表示式格式以及應用場景?
為了解決那些功能很簡單的需求而設計的一句話函式。
64:字串常用功能?
長度 迴圈 鍵、值、鍵值對 刪除 新增 索引 字典常用操作 包含 長度 切片 索引 元組常用操作 包含 迴圈 切片 長度 刪除 追加 切片 索引 列表常用操作 切片 索引 長度 分割 移除空白
words = 'today is a wonderfulday'。 print(words.strip('today'))#如果strip方法指定一個值的話,那麼會去掉這兩個值。 print(words.count('a'))#統計字串出現的次數。 print(words.index('is'))#找下標。 print(words.index('z'))#找下標如果元素不找不到的話,會報錯。 print(words.find('z'))#找下標,如果元素找不到的話,返回-1。 print(words.replace('day','DAY'))#字串替換。 print(words.isdigit())#判斷字串是否為純數字。 print(words.islower())#判斷字串是否為小寫字母。 print(words.isupper())#判斷字串是否為大寫字母。 print(words.startswith('http'))#判斷是否以某個字串開頭。 print(words.endswith('.jpg'))#判斷是否以某個字串結尾。 print(words.upper())#將字串變成大寫。 print(words.lower())#將字串變成小寫。
65:列舉布林值為False的常見值?
False 0 [] () {} 字串 布林值 零 列表 元組 字典。
66:xreadlines和readlines的區別?
二者使用時相同,但返回型別不同,xreadlines返回的是一個生成器,readlines返回的是list。
67:xrange和range的區別?
Python 3.x已經去掉xrange,全部用range代替。
range和xrange都是在迴圈中使用,輸出結果一樣。
range返回的是一個list物件,而xrange返回的是一個生成器物件(xrange object)。
xrange則不會直接生成一個list,而是每次呼叫返回其中的一個值,記憶體空間使用極少,因而效能非常好。
xrange函式說明:用法與range完全相同,所不同的是生成的不是一個數組,而是一個生成器。
range函式說明:range([start,] stop[, step]),根據start與stop指定的範圍以及step設定的步長,生成一個序列。
68:Python3和Python2中 int 和 long的區別?
long整數型別被Python3廢棄,統一使用int
69:用一行程式碼實現數值交換。
b = 2 a = 1
a,b = b,a
70:列舉 Python2和Python3的區別?
在Python2中,print 被視為一個語句而不是一個函式,這是一個典型的容易弄混的地方,因為在 Python 中的許多操作都需要括號內的引數來執行。
71:三元運算規則以及應用場景?
(expr1) ? (expr2) : (expr3);
三元運算子的功能與“if...else”流程語句一致,它在一行中書寫,程式碼非常精練、執行效率更高。
72:位元組碼和機器碼的區別?
機器碼存在著多至100000種機器語言的指令。這意味著不能把這些種類全部列出來。儘管機器語言好像是很複雜的,然而它是有規律的。8086到Pentium的機器語言指令長度可以從1位元組到13位元組。機器語言是微處理器理解和使用的,用於控制它的操作二進位制程式碼。用機器語言編寫程式,程式設計人員要首先熟記所用計算機的全部指令程式碼和程式碼的涵義。手程式設計序時,程式設計師得自己處理每條指令和每一資料的儲存分配和輸入輸出,還得記住程式設計過程中每步所使用的工作單元處在何種狀態。這是一件十分繁瑣的工作,編寫程式花費的時間往往是實際執行時間的幾十倍或幾百倍。而且,編出的程式全是些0和1的指令程式碼。總結:機器碼是電腦CPU直接讀取執行的機器指令,執行速度最快機器碼就是計算機可以直接執行,並且執行速度最快的程式碼。
位元組碼主要為了實現特定軟體執行和軟體環境、硬體環境無關。位元組碼的實現方式是通過編譯器和虛擬機器器。編譯器將原始碼編譯成位元組碼,特定平臺上的虛擬機器器將位元組碼轉譯為可以直接執行的指令。位元組碼的典型應用為Java語言。位元組碼通常指的是已經經過編譯,但與特定機器碼無關,需要直譯器轉譯後才能成為機器碼的中間程式碼。位元組碼通常不像原始碼一樣可以讓人閱讀,而是編碼後的數值常量、引用、指令等構成的序列。位元組碼是一種中間碼。總結:位元組碼是一種中間狀態(中間碼)的二進位制程式碼(檔案)。需要直譯器轉譯後才能成為機器碼。
73:ascii、unicode、utf-8、gbk 區別?
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字元編碼,又稱萬國碼。由Ken Thompson於1992年建立。現在已經標準化為RFC 3629。UTF-8用1到6個位元組編碼UNICODE字元。用在網頁上可以同一頁面顯示中文簡體繁體及其它語言(如英文,日文,韓文)。
GBK是隻用來編碼漢字的,GBK全稱《漢字內碼擴充套件規範》,使用雙位元組編碼。
Unicode能夠表示全世界所有的位元組。在表示一個Unicode的字元時,通常會用“U+”然後緊接著一組十六進位制的數字來表示這一個字元。在基本多文種平面(英文為 Basic Multilingual Plane,簡寫 BMP。它又簡稱為“零號平面”, plane 0)裡的所有字元,要用四位十六進位制數(例如U+4AE0,共支援六萬多個字元);在零號平面以外的字元則需要使用五位或六位十六進位制數了。舊版的Unicode標準使用相近的標記方法,但卻有些微的差異:在Unicode 3.0裡使用“U-”然後緊接著八位數,而“U+”則必須隨後緊接著四位數。
ASCII碼使用一個位元組編碼,所以它的範圍基本是隻有英文字母、數字和一些特殊符號 ,只有256個字元。
74:求出下列的結果。
v6 = 0 or False and 1 False
v5 = 0 and 2 or 1 or 4 1
v4 = 0 and 2 or 1 1
v3 = 0 and 2 and 0
v2 = 1 and 3 3
v1 = 1 or 3 1
75:什麼是pickling和unpickling?
Pickle模組讀入任何Python物件,將它們轉換成字串,然後使用dump函式將其轉儲到一個檔案中——這個過程叫做pickling。
反之從儲存的字串檔案中提取原始Python物件的過程,叫做unpickling。
76:python遞迴的最大層數?
程式表明在3925-3929之間 一般是在998
77:請編寫一個函式實現將IP地址轉換成一個整數。
def ipfunc(ip):
a = ip.split('.')
s = ''
l = []
for i in a:
i = bin(int(i))[2:]
i = i.rjust(8, '0')
l.append(i)
s = s.join(l)
return s
ipfunc("192.168.2.13")
再將以上二進位制拼接起來計算十進位制結果:00001010 00000011 00001001 00001100 = ?
int(ipfunc("192.168.2.13"),2)
78:Python程式設計常用技巧?
#使用yield節省記憶體開銷
def read_file(fpath):
with open(fpath, 'rb') as f:
BLOCK_SIZE = 1024
while True:
if block:
block = f.read(BLOCK_SIZE)
yield block
yield 的例子來源於檔案讀取。如果直接對檔案物件呼叫 read() 方法,會導致不可預測的記憶體佔用。好的方法是利用固定長度的緩衝區來不斷讀取檔案內容。通過 yield,我們不再需要編寫讀檔案的迭代類,就可以輕鬆實現檔案讀取。[1,2,3,4]這個是迭代器,用for來迭代它,生成器(x for x in range(4))也是迭代器的一種,但是你只能迭代它們一次.原因很簡單,因為它們不是全部存在記憶體裡,它們只在要呼叫的時候在記憶體裡生成,yield的用法和關鍵字return差不多,下面的函式將會返回一個生成器。迭代的時候碰到yield立刻return一個值,下一次迭代的時候,從yield的下一條語句開始執行。
for line in f 這種用法是把檔案物件f當作迭代物件,系統將自動處理IO快取和記憶體管理。
組合工具
izip() # 類似於zip()函式,只是返回的是一個迴圈器。
compress('ABCD', [1, 1, 1, 0]) # 根據[1, 1, 1, 0]的真假值情況,選擇第一個引數'ABCD'中的元素。A, B, C。
combinations_with_replacement('abc', 2) # 與上面類似,但允許兩次選出的元素重複。即多了aa, bb, cc。
combinations('abc', 2) # 從'abcd'中挑選兩個元素,比如ab, bc, ... 將所有結果排序,返回為新的迴圈器。
chain([1, 2, 3], [4, 5, 7]) # 連線兩個迴圈器成為一個1, 2, 3, 4, 5, 7。
函式式工具
dropwhile(lambda x: x < 5, [1, 3, 6, 7, 1])
takewhile(lambda x: x < 5, [1, 3, 6, 7, 1])
ifilter函式與filter()函式類似,只是返回的是一個迴圈器。
starmap(pow, [(1, 1), (2, 2), (3, 3)])
無窮迴圈器
repeat(10, 5) #重複10,共重複5次
repeat(1.2) #重複1.2,構成無窮迴圈器,即1.2, 1.2, 1.2, ...
cycle('abc') #重複序列的元素,既a, b, c, a, b, c ...
count(5, 2) #從5開始的整數迴圈器,每次增加2,即5, 7, 9, 11, 13, 15 ...
*args和**kw
*args要麼是表示呼叫方法大的時候額外的引數可以從一個可迭代列表中取得,要麼就是定義方法的時候標誌這個方法能夠接受任意的位置引數。接下來提到的**,**kw代表著鍵值對的字典,也就是說,你不用一個個字典用key來取value了。
json.dumps()/loads() 儲存字典結構
json.dumps : dict轉成str 。
json.loads:str轉成dict。
善用traceback 追蹤深層錯誤
對於輕量級迴圈,可儘量使用列表推導式,熟練使用列表推導式可以很多情況下代替map,filter等操作。
islice() # 類似於slice()函式,只是返回的是一個迴圈器
79:資料型別。
Number
在JavaScript中的雙精度浮點格式
String
雙引號的反斜槓轉義的Unicode
Boolean
true 或 false
Array
值的有序序列
Value
它可以是一個字串,一個數字,真的還是假(true/false),空(null )等
Object
無序集合鍵值對
Whitespace
可以使用任何一對中的令牌
null
empty
80:json序列化時,預設遇到中文會轉換成unicode,如果想要保留中文怎麼辦?如果需要保留date或者datetime日期格式的資料,該如何處理?
第一種方案:定義處理類。
實數虛數
import json
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, complex):
return [obj.real, obj.imag]
return json.JSONEncoder.default(self, obj)
資料型別為datetime 與 date
class CJsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(obj, date):
return obj.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, obj)
json.dumps(datalist, cls=CJsonEncoder)
第二種方案:不用定義類,直接用strftime方法處理。
如果不想定義類,直接在我們獲取的date或者datetime物件後面用上strftime方法進行格式化也可以。
處理保留中文的方案。
dict1 = {'name': '李小萌', 'age': 10}
#序列化的時候新增一個引數 ensure_ascii=False
print(json.dumps(dict1, ensure_ascii=False))
81:什麼是斷言?應用場景?
Python的assert是用來檢查一個條件,如果它為真,就不做任何事。如果它為假,則會丟擲AssertError並且包含錯誤資訊。例如:
防禦型的程式設計: 執行時檢查程式邏輯 檢查約定 程式常量 檢查文件。
不要用它測試使用者提供的資料
不要用斷言來檢查你覺得在你的程式的常規使用時會出錯的地方。斷言是用來檢查非常罕見的問題。你的使用者不應該看到任何斷言錯誤,如果他們看到了,這是一個bug,修復它。
有的情況下,不用斷言是因為它比精確的檢查要短,它不應該是懶碼農的偷懶方式。
不要用它來檢查對公共庫的輸入引數,因為它不能控制呼叫者,所以不能保證呼叫者會不會打破雙方的約定。
不要為你覺得可以恢復的錯誤用斷言。換句話說,不用改在產品程式碼裡捕捉到斷言錯誤。
不要用太多斷言以至於讓程式碼很晦澀。
82:有用過with statement嗎?它的好處是什麼?
with語句的作用是通過某種方式簡化異常處理,它是所謂的上下文管理器的一種。
with open('output.txt', 'w') as f: f.write('Hi there!')
當你要成對執行兩個相關的操作的時候,這樣就很方便,以上便是經典例子,with語句會在巢狀的程式碼執行之後,自動關閉檔案。這種做法的還有另一個優勢就是,無論巢狀的程式碼是以何種方式結束的,它都關閉檔案。如果在巢狀的程式碼中發生異常,它能夠在外部exception handler catch異常前關閉檔案。如果巢狀程式碼有return/continue/break語句,它同樣能夠關閉檔案。
我們可以用contextlib中的context manager修飾器來實現,比如可以通過以下程式碼暫時改變當前目錄然後執行一定操作後返回。
from contextlib import contextmanager import os @contextmanager def working_directory(path): current_dir = os.getcwd() os.chdir(path) try: yield finally: os.chdir(current_dir) with working_directory("data/stuff"): # do something within data/stuff # here I am back again in the original working directory
83:使用程式碼實現檢視列舉目錄下的所有檔案。
import os
# 可以通過相對路徑 print(os.listdir('../檔名稱'))
#也可以通過絕對路徑 得到的結果是一個列表的形式可以遍歷出來 print(os.listdir('絕對路徑'))
84:簡述 yield和yield from關鍵字。
yield from iterable本質上等於for item in iterable: yield item的縮寫。
可迭代物件與迭代器的區別
可迭代物件:指的是具備可迭代的能力,即iterable,在Python中指的是可以通過for in 語句去逐個訪問元素的一些物件,比如元組tuple,列表list,字串string,檔案物件file 等。
迭代器:指的是通過另一種方式去一個一個訪問可迭代物件中的元素,即iterator。在python中指的是給內建函式iter()傳遞一個可迭代物件作為引數,返回的那個物件就是迭代器,然後通過迭代器的next()方法逐個去訪問。
生成器:生成器的本質就是一個逐個返回元素的函式,即“本質——函式”。
yield from:簡單地說,yield from generator 。實際上就是返回另外一個生成器。
85:提高python執行效率的方法。
使用生成器,因為可以節約大量記憶體。
迴圈程式碼優化,避免過多重複程式碼的執行。
核心模組用Cpython PyPy等,提高效率。
多程序、多執行緒、協程。
多個if elif條件判斷,可以把最有可能先發生的條件放到前面寫,這樣可以減少程式判斷的次數,提高效率。
86:IOError AttributeError ImportError IndentationError IndexError KeyError SyntaxError NameError分別代表什麼異常。
IOError:輸入輸出異常。
AttributeError:試圖訪問一個物件沒有的屬性。
ImportError:無法引入模組或包,基本是路徑問題。
IndentationError:語法錯誤,程式碼沒有正確的對齊。
NameError:使用一個還未賦予物件的變數。
SyntaxError:Python程式碼邏輯語法出錯,不能執行。
KeyError:試圖訪問你字典裡不存在的鍵。
IndexError:下標索引超出序列邊界。
IndentationError:語法錯誤,程式碼沒有正確的對齊。