1. 程式人生 > >[學習總結] python語言學習總結 (二)

[學習總結] python語言學習總結 (二)

1.python中的拆包

之前就只寫了*可以是未知數量的引數,**可以傳入未知數量命名引數。這次詳細記下拆包。

def f1(a, *l):
    print(a)
    # 不拆包
    print(l)
    # 拆包
    print(*l)
    f2(l)
    f2(*l)


def f2(*l):
    print(l)
    print(*l)


def f3(**kw):
    # 不拆包
    print(kw)
    # 得到鍵名
    print(*kw)
    # 拆包,鍵名對應
    f4(**kw)
    
# 注意,python中沒辦法輸出**kw,不信可以自己試試。。 def f4(a, b): print(a, b) f3(a=1, b=2) f1(1, 2, 3) ''' {'a': 1, 'b': 2} a b 1 2 1 (2, 3) 2 3 ((2, 3),) (2, 3) (2, 3) 2 3 '''

 

我試圖通過這段程式碼的執行情況搞清楚拆包,實際上結果也特別明顯。

其實python給f1和f2函式傳入的引數是個元組,也就是形式引數被轉換為元組傳入了f1和f2中作為實參,這應該是函式給我們做的裝包工作,這個工作對我們在函式裡操作是很方便的,而從未拆包和拆包的f2的輸出來看,我們的理解是正確的。

同樣的,**kw傳入的引數其實是個字典,傳入之後會隱式地進行裝包工作,也就是將a=1,b=2裝包成{'a':1,'b':2}的字典,這樣方便了我們在函式中提取相應引數,我覺得還是很有用的。需要注意的是,我們無法通過print(**kw)得到a=1,b=2的輸出結果,因為print函式貌似不支援這種輸出,可以自己嘗試下。而從f4的輸出看出,我們的理解是正確的。

因此,我們可以在以下場景用到拆包操作。

1.我們有一個元組,想把這個元組的資料分別作為引數傳入。其實就是上面f2函式實現的。

2.我們有一個字典,想把這個字典的資料分別作為引數傳入。其實就是上面f4函式實現的。

 

2.python中的切片

說實在話,切片用到的次數非常多,因為經常操作字串、list和numpy,所以這個東西用到的次數非常多。

以一個簡單的字串為例

str = "abcdefg"


print(str[0:2:1], str[0:2:-1], str[:], str[::-1], str[::-2])


'''
ab  abcdefg gfedcba geca
'''

切片最常用的是一個左右中括號的操作;通過指定的下標來訪問一組序列的元素,其實就切片操作。

中括號中我們可以指定三個引數,其中第一個引數代表要取的序列的起始index,我們選0,就是從最開始選,第二個引數是結束index,但是不包含這個index對應的資料,從以上輸出中我們是可以看出來的,第三個引數是步長,步長為1,那麼他就從左往右一個一個取;步長為-1,那麼他就從右往左一個一個取,步長為負就是反方向取,因此我們可以填-2,那麼他就從右往左以兩個步長取元素。

其中呢,後面的冒號是可以省略的,也就是可以不填步長,預設就是1,只有一個冒號而不填任何引數就是複製這個序列,而前兩個引數空,只把步長設為1其實就是倒置這個序列。

 

3.python中的名稱空間

python中的名稱空間我覺得還是要搞清楚的,這樣對理解python這門語言還是很有幫助的。
名稱空間(namespace):名稱空間是名字和物件的對映。也就是可以把一個namespace理解為一個字典,實際上很多當前的Python實現namespace就是用的字典。各個名稱空間是獨立的,沒有任何關係的,所以一個名稱空間中不能有重名,但不同的名稱空間是可以重名而沒有任何影響。


Build-in
....Global
........Enclosed
............Local

 

可見確實是個層級關係。
我們來分別解釋這四個名稱空間,
Build-in:python直譯器啟動產生的字典,用於存放python內建的名字。
Global:執行python檔案時,存放檔案級定義的名字,就是被import的時候建立,在直譯器退出的時候才被刪除。
Enclosed:指的是一個函式被另一個函式包含時的名稱空間。
Local:執行檔案過程中,呼叫函式時產生的名稱空間,用來存放函式內定義的名字,由於生命週期的原因,函式呼叫結束後該名字會被刪除。

Python在查詢變數時候按照從內至外的順序查詢變數,可以說成是LEGBD順序。
作用域(scope):作用域是Python程式(文字)的某一段或某些段,在這些地方,某個名稱空間中的名字可以被直接引用。這個作用域就是這個名稱空間的作用域。

下面用程式碼來理解一下作用域。

from copy import copy
a = 5
print("***build-in and globals***")
#  print(type(list(globals().keys())))
globals_init = copy(list(globals().keys()))
print("\n".join(globals_init))  # 輸出的是build-in的名稱空間下的名字key


def f1(b=3):
    c = 4
    print("***globals in f1***", *(globals().keys() - globals_init), sep="\n")
    #  解釋下這裡,globals().keys()返回的是list,list相減得到的是set,然後對set解包就可以輸出了,也可以把set轉化為list用.join輸出
    print("***locals in f1***", *(locals().keys()), sep="\n")
    
    
    def f2():
        c = 5
        print("***locals in f2***", *(locals().keys()), sep="\n")
    print("c=", c)
    f2()
    print("c=", c)


    def f3():
        nonlocal c
        c = 6
        print("***locals in f3***", *(locals().keys()), sep="\n")
    print("c=", c)
    f3()
    print("c=", c)


f1()

'''
***build-in and globals***
__name__
__doc__
__package__
__loader__
__spec__
__annotations__
__builtins__
__file__
__cached__
copy
a
***globals in f1***
globals_init
f1
***locals in f1***
b
c
c= 4
locals in f2
c
c= 4
c= 4
locals in f3
c
c= 6
'''

咱們從這裡可以看出,不同作用域對應的名稱是相互獨立的,在函式內如果和函式外有相同的變數名稱,會預設把近的那個作為要找到的變數,如果要訪問函式外的比如a怎麼辦呢,很簡單,函式裡面寫上global a 即可,否則你的操作就相當於在函式內的local裡建立了一個新變數。函式巢狀的時候使用nonlocal去操作被套函式外的local變數,甚至也可以通過global操作全域性變數。上面的例子仔細看看應該是理解了。

 

4.python中的一些高階函式總結

分別是map、filter、reduce、sorted。其中sorted函式之前已經寫過了,但是當時沒有用到引數key,這次查了一下,發現key就是自定義排序規則,比如我們讓key=abs,那麼就會按照絕對值大小排序,當然我們也可以自定義函式,我這裡用lambda定義了匿名函式來對x平方大小排序,然後映射回原list。map函式通過建立一個對映,對後面的range通過呼叫前面的匿名函式形成一個數值對映,然後得到map結果,我們將這個結果轉為list輸出。filter在map的基礎上呢,相當於加上了一層判斷,其實filter也會對後面的list生成一個值的對映,但是filter會利用函式作為引數做一層判斷,保留滿足條件的結果。reduce函式呢,可以允許我們兩兩呼叫函式引數,最終只得到一個結果(如例子),這個例子的計算結果其實是1*2*3*4=24也就是也就是先1*2=2,再2*3=6,再6*4=24的結果。;lambda沒什麼說的了。不是很全,後面會再總結。

from functools import reduce
import random
a = map(lambda x: x**2, range(1, 5))
print(list(a))
#  [1, 4, 9, 16]

b = filter(lambda x: x>0, [1,-5,6,0])
print(list(b))
#  [1, 6]

c = reduce(lambda x,y: x*y,range(1,5))
print(c)
#  24

lst = [x * (-1)**x for x in range(1,10)]
random.shuffle(lst)
print(lst)
d = sorted(lst,key = lambda x: x**2,reverse = True)
print(d)
#  [-3, -5, -7, 4, 6, 8, -1, 2, -9]
#  [-9, 8, -7, 6, -5, 4, -3, 2, -1]