python基礎知識(持續更新)

1.Python解釋器種類以及特點

CPython

c語言開發的 使用最廣的解釋器

IPython

基於cpython之上的一個交互式計時器 交互方式增強 功能和cpython一樣

PyPy

目標是執行效率 採用JIT技術 對python代碼進行動態編譯,提高執行效率

JPython

運行在Java上的解釋器 直接把python代碼編譯成Java字節碼執行

IronPython

運行在微軟 .NET 平臺上的解釋器,把python編譯成. NET 的字節碼

2.python的遞歸深度

遞歸深度

Python語言默認的遞歸深度是很有限的,當遞歸深度超過值的時候,就會引發RuntimeError異常**

Python專門設置的一種機制用來防止無限遞歸造成Python溢出,這個值理論上1000,實際運行時在900多次時就會報錯

解決方案

最大遞歸次數是可以重新調整的。解決的方式是手工設置遞歸調用深度:

import sys 
sys.setrecursionlimit(1000000) #執行這個代碼後,遞歸深度調整到1000000層,基本上夠用了

其他辦法:改成非遞歸

3.python的深淺拷貝

定義

深拷貝的時候python將所有數據在內存中新建了一份,所以如果你修改新的模版的時候老模版不會變。相反,在淺copy 的時候,python僅僅將最外層的內容在內存中新建了一份出來,第二層並沒有在內存中新建,所以你修改了新模版,默認模版也被修改了

下面我們先看一個具體的例子

淺拷貝

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}}

總結

  1. 淺拷貝時,修改的元素類型是可變類型時,他變我也變,修改的類型是不可變類型時,他變我不變
  2. 深拷貝時,他變我不變

4. python的匿名函數

  1. 爲了解決那些功能很簡單的需求而設計的一句話函數

  2. 函數名 = lambda 參數 :返回值

  3. 匿名函數不管邏輯多複雜,只能寫一行,且邏輯執行結束後的內容就是返回值

    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 的一個重要部分。簡單地說:他們是修改其他函數的功能的函數。他們有助於讓我們的代碼更簡短,裝飾器本質上是一個高階函數,所以裝飾器也可以有自己的參數

日誌裝飾器

日誌是裝飾器運用的另一個亮點

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作用

被裝飾後的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變),所以,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。寫一個decorator的時候,最好在實現之前加上functools的wrap,它能保留原有函數的名稱和docstring

6. *args,**kwargs?參數是什麼?

如果我們不確定要往函數中傳入多少個參數,或者我們想往函數中以列表和元組的形式傳參數時,那就使要用*args;如果我們不知道要往函數中傳入多少個關鍵詞參數,或者想傳入字典的值作爲關鍵詞參數時,那就要使用**kwargs

7.python中的負號“-”

字符串和列表都適用

ss = "abcd"

#output: abc
#打印字符串長度len(ss)-1的內容
print(ss[:-1])

#output: dcba
#字符串反轉,-1,表示依次反轉
print(ss[::-1])

#output: db
#字符串反轉,-2,表示相隔一個字符反轉
print(ss[::-2])
#output: c
#字符串的倒數第二個字符
print(ss[::-2])

8. python單下劃線和雙下劃線

單下劃線

常用於模塊中,在一個模塊中以單下劃線開頭的變量和方法會被默認劃入模塊內部範圍。當使用 from my_module import * 導入時,單下劃線開頭的變量和方法是不會被導入的。但使用 import my_module 導入的話,仍然可以用 my_module._var 這樣的形式訪問屬性或方法

雙下劃線

雙下劃線開頭和結尾的是一些 python 的“魔術”對象,如類成員的 __init__、__del__、__add__、__getitem__ 等,以及全局的__file__、__name__等,多用來表示私有變量或類

9.python的內存管理

Python的內存管理是由私有heap空間管理的。所有的Python對象和數據結構都在一個私有heap中。程序員沒有訪問該heap的權限,只有解釋器才能對它進行操作。爲Python的heap空間分配內存是由Python的內存管理模塊進行的,其核心API會提供一些訪問該模塊的方法供程序員使用。Python有自帶的垃圾回收系統,它回收並釋放沒有被使用的內存,讓它們能夠被其他程序使用

10. 多進程與多線程的區別

1. 一個程序至少有一個進程,一個進程至少有一個線程

2.線程的劃分尺度小於進程,使得多線程程序的併發性高

3.進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率

4.線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制

5.從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別

11.文件操作:read,readline和readlines

read

讀取整個文件將文件內容放到一個字符串變量中,劣勢是:如果文件非常大,尤其是大於內存時,無法使用read()方法

readline

每次讀取一行;返回的是一個字符串對象,保持當前行的內存,缺點:比readlines慢得多

readlines

一次性讀取整個文件;自動將文件內容分析成一個行的列表

12.如何判斷單向鏈表中是否有壞

首先遍歷鏈表,尋找是否有相同地址,藉此判斷鏈表中是否有環。如果程序進入死循環,則需要一塊空間來存儲指針,遍歷新指針時將其和儲存的舊指針比對,若有相同指針,則該鏈表有環,否則將這個新指針存下來後繼續往下讀取,直到遇見NULL,這說明這個鏈表無環

13.sort和sorted的區別

1.sorted執行之後返回一個新的列表,sort是在原有的列表做修改

2. sorted 可以對更多組合排序,sort只能對列表排序


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可以對元祖進行排序

14. 列表解析式

列表解析式又叫列表推導式,和標準的python循環相比,不僅可讀性強,而且需要的代碼量也是最少的,執行速度也是比標準循環快樂不少,對於列表推導式,我們可以從列表中選擇具體的元素,並做一些操作和判斷,從而創建新的列表。值得注意的是,我們甚至能使用 Pandas Series 或 NumPy Array 進行列表推導操作,廢話不多說,直接上代碼


#標準的循環模式
list1 = [1,3,2,6,4]
list2 = []
for one in list1:
    list2.append(one)
    
#列表推導式
list1 = [1,3,2,6,4]
list2 = [one for one in list1]
    

代碼量明顯降低了很多,當然也可以在裏面加入一些條件處理語句


#標準的循環模式
list1 = [1,3,2,6,4]
list2 = []
for one in list1:
    if one > 2:
        list2.append(one)
    
#列表推導式
list1 = [1,3,2,6,4]
list2 = [one for one in list1 if one > 2]
    

從代碼量上,很明顯列表推導式簡潔了很多,只要用習慣了列表推導式就沒必要再去使用python標準循環

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章