1.深淺拷貝 在Python中將一個變數的值傳遞給另外一個變數通常有三種:賦值、淺拷貝、深拷貝 Python數據類型可氛圍基本數據類型包括整型、字元串、布爾及None等,還有一種由基本數據類型作為最基本的元素所組成的像列表、元組、字典等。 在Python中基本數據類型的賦值、深淺拷貝沒有任何意義,都 ...
1.深淺拷貝
在Python中將一個變數的值傳遞給另外一個變數通常有三種:賦值、淺拷貝、深拷貝
Python數據類型可氛圍基本數據類型包括整型、字元串、布爾及None等,還有一種由基本數據類型作為最基本的元素所組成的像列表、元組、字典等。
在Python中基本數據類型的賦值、深淺拷貝沒有任何意義,都是指向同一塊記憶體地址,也不存在層次問題。
下麵看基本數據類型的深淺拷貝
import copy n1 = 'abc' n2 = n1 n3 = copy.copy(n1) n4 = copy.deepcopy(n1) print(id(n1)) #輸出140350336680040 print(id(n2)) #輸出140350336680040 print(id(n3)) #輸出140350336680040 print(id(n4)) #輸出140350336680040
以上代碼說明Python的copy模塊的copy和deepcopy函數實現了淺拷貝和深拷貝,可以看到,賦值、淺拷貝和深拷貝最後的id(Python記憶體地址的表達方式)都是一樣的
接下來討論其他的列表、元組、字典等非基本數據類型對象的賦值、深淺拷貝的區別
假設字典n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]}
賦值是將變數的記憶體賦給另一個變數,讓另一個變數指向那個記憶體地址
淺拷貝
淺拷貝就是在記憶體中將第一層額外開闢空間進行存放
n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]} print(id(n1)) #140350328984328 n3 = copy.copy(n1) print(id(n3)) #140350328986504可以看n3的記憶體地址已經和n1不同了 print(id(n1['k3'])) #140350328603976 print(id(n3['k3'])) #140350328603976 字典里的列表還是指向同一個列表
深拷貝
深拷貝就是在記憶體中將數據重新創建一份,不僅僅是第一層,第二層、第三層...都會重新創建
n1 = {"k1": "abc", "k2": 123, "k3": ["abc", 123]} print(id(n1)) #140350328984328 n3 = copy.deepcopy(n1) print(id(n1['k3'])) #140350328603976 print(id(n3['k3'])) #140350328604296 #可以看到第二層的列表也拷貝了一份,記憶體地址已經完全不一樣 #註意,這僅局限於非基本數據類型,基本數據類型還是同一個記憶體地址
2.函數
函數的定義及調用
定義一個函數要使用def關鍵字,依次寫出函數名、括弧、括弧中的參數和冒號:,然後用縮進的代碼塊寫函數體,函數體內可以調用return語句返回結果。
函數名作為函數的名稱,也可以像變數一樣進行賦值操作、甚至作為參數進行傳遞。
函數的參數
1)位置參數
這是最常見的定義方式,一個函數可以定義任意個參數,每個參數用逗號分隔,例如:
def Foo1(arg1, arg2):
print(arg1, arg2)
用這種方式定義的函數在調用的的時候也必須在函數名後的小括弧里提供個數相等的值(實際參數),而且順序必須相同,也就是說在這種調用中,形參和實參的個數必須一致,而且必須一一對應,也就是說第一個形參對應這第一個實參。例如:
Foo1('abc', 123)
#輸出結果 abc 123
也可以通過如下方式傳遞參數,而不必考慮順序問題,但數量無論如何必須一致。
foo3(arg2 = 123, arg1 = 'abc')
2)預設參數
我們可以給某個參數指定一個預設值,當調用時,如果沒有指定那個參數,那個參數就等於預設值
def Foo2(arg1, arg2 = 123): print(arg1, arg2)
調用
Foo2('abc') Foo2('abc', 345) ''' 執行結果 abc 123 abc 345 註意:定義的時候預設參數必須放到所有位置參數的後面進行定義,否則會報語法錯誤 '''
3)可變參數
可變參數就是傳入的參數個數是可變的,也可以是0個,例如
def Foo3(*args):
print(args)
調用
Foo3(1, 2, 'abc') #執行結果 (1, 2, 'abc') 可以看到我們傳遞了三個參數都被Python轉化為元祖,保存到args中了,這樣我們就可以通過索引對參數記性調用,或者通過for in進行遍歷
4)關鍵字參數
可變參數在調用過程中會組裝成元組,元組只能通過索引進行調用,有時不是很方便,故Python可以通過關鍵字索引將傳入的參數組裝成字典
def Foo4(**kwargs): print(kwargs, type(kwargs)) Foo4(k1 = 'abc', k2 = 123) #執行結果 {'k2': 123, 'k1': 'abc'} <class 'dict'> #關鍵字參數允許傳入0個或任意個參數名的參數,0個的話就是一個空字典
參數組合
在Python中定義函數,可以用必選參數(位置參數)、預設參數、可變參數、關鍵字參數這幾種參數進行組合使用,但是順序必須是,必選參數、預設參數、可變參數、關鍵字參數。
def Foo5(arg1, arg2='abc', *args, **kwargs): print('arg1:', arg1) print('arg2:', arg2) print('args', args) print('kwargs', kwargs) Foo5(123, 'abc', 456, 'def', k1=123, k2='abc') ''' 執行結果 arg1: 123 arg2: abc args (456, 'def') kwargs {'k1': 123, 'k2': 'abc'} '''
lambda匿名函數
匿名函數就是功能非常簡單隻需要一行代碼就可以實現的,例如,求圓形面積
f = lambda r: 3.14 * r * r print(f(4)) # 輸出 50.24 #r相當於匿名函數的參數,當然也可以有多個參數,不用在寫return,表達式就是返回的結果。
使用匿名函數有個好處,因為函數沒有名字,不用擔心函數名衝突,此外匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變數,再利用變數調用該函數。
關於函數的return語句
1)函數可以沒有return語句,沒有就預設返回None
2)return語句有點類似迴圈的break,當函數執行到return語句時候,直接跳出函數的執行
3)return可以返回多個值,多個值可以用兩個變數接收,也可以額一個變數接收
def Foo6(): return 123, 'abc' res1, res2 =Foo6() print('res1:', res1) #res1: 123 print('res2:', res2) #res2: abc res = Foo6() print('res:', res) #res: (123, 'abc') #返回多個值就是返回一個元組,使用兩個變數接收的時候回將元組的元素與變數一一對應賦給多個變數
關於可變參數和關鍵字參數的傳遞小技巧
我們已經知道可變參數和關鍵字參數分別將傳遞的參數組裝成元組和字典,那麼我們同樣可以直接將元組、列表和字典直接傳遞給函數作為參數,傳遞的時候列表和元組要在變數前面加一個*,字典要在前面加兩個*,否則函數還是會把它們當成一個普通的參數傳遞進行處理
def Foo7(*args, **kwargs): print(args) print(kwargs) li = [1, 2, 3] dic = {'k':1, 'k2':2} Foo7(li, dic) Foo7(*li, **dic) ''' 執行結果 ([1, 2, 3], {'k': 1, 'k2': 2}) {} #可以看到兩個參數都被可變參數接收了,關鍵字參數啥也沒有 (1, 2, 3) {'k': 1, 'k2': 2} '''
Python常用的內置函數
只重點關註標記的內置函數
print(abs(-10)) #輸出10abs 返回絕對值
print(all([1, True, 1 == 1])) #Trueall 可迭代對象(列表、元祖等)中所有的元素都是True,則返回True,否則返回False。相當於and
print(any([None, "", [], (), {}, 0, False])) #False print(any([None, "", [], (), {}, 0, True]) )#True #通常情況下“空”(None,空字元串、空列表,0等等)都是表示Falseany 相當於or
print(bin(10)) #'0b1010'bin 整數轉換二進位字元串
print(bool()) #False print(bool(10)) #Trueclass bool 返回或者新建一個布爾值
print(chr(89999)) #'\U00015f8f' print(chr(97)) #'a'chr 整數轉成unicode編碼所對應的位元組
print(dict()) #{} print(dict(k1 = 'v1', k2 = 'v2')) #{'k1': 'v1', 'k2': 'v2'} print(dict((['k1', 'v1'], ['k2', 'v2']))) #{'k1': 'v1', 'k2': 'v2'} print(dict({'k1':'v1', 'k2':'v2'})) #{'k1': 'v1', 'k2': 'v2'}dict 創建字典對象
print(dir("")) #['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']dir 查看所有變數名和方法名
print(divmod(10, 3)) #(3, 1) 返回兩個數的得商和餘數組成的元組,相當於(a // b, a % b)divmod返回兩個數的得商和餘數組成的元組
enu = enumerate(['abc', 'def', 'ghi']) print(enu) for i in enu print(i) ''' 返回一個迭代器,每次迭代返回一個元組包括一個計數器,和對iterable迭代取得的值,iterable可迭代對象,包括列表、元祖等。start表示計數器的開始值,預設是0 執行結果 <enumerate object at 0x0000000BE2D53510> # 可以看到返回的是一個enumerate對象 (0, 'abc') (1, 'def') (2, 'ghi') ''' #註意:返回的是是一個迭代器,迭代完了空了,如果需要重覆使用,最好轉化為一個列表對象保存到變數中,並且計數器是從0開始計數的 li = list(enumerate(['abc', 'def', 'ghi'])) print(li) #[(0, 'abc'), (1, 'def'), (2, 'ghi')] #還可以指定start的開始值 li = list(enumerate(['abc', 'def', 'ghi'], 2)) print(li) #[(2, 'abc'), (3, 'def'), (4, 'ghi')]enumerate(iterable, start=0)
print(eval('3 + 4 * (1 - 3)')) #-5 #將的字元串形式的算數表達式進行計算,並返回結果eval(expression, globals=None, locals=None)
def func(num): if num % 2 ==0: return True else: return False nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] print(list(filter(func, nums))) ''' 接收一個函數和一個可迭代對象,將可迭代對象的每一個元素都作為參數執行函數,函數返回為真的放到一個新的可迭代對象中,並將新的可迭代對象返回 執行結果 [2, 4, 6, 8, 10, 12, 14, 16, 18] '''filter(function, iterable)
print('0.5') #0.5 print(0.5) #0.5 #創建一個浮點類型的對象class float([x])
#返回某個對象的幫助信息help([object])
print(hex(23)) #'0x17' #返回一個整數的16進位表達式hex(x)
print(id(1)) #10455040 #返回對象的id(可以理解為Python為每個對象的編號,或者理解為是Python對象記憶體地址的表達形式)id(object)
s = input('python>>') print(s) ''' 輸入123 輸出'123' 接受用戶從控制台的輸入,並將用戶輸入的信息,以字元串的返回,prompt表示輸入時前顯示的字元串 '''input([prompt])
print(int()) #0 print(int('1010', base=2)) #10 #創建一個整數類型的對象,預設如果創建的0,如果傳遞的是字元串類型的,可以把字元串表達式所表示的整數轉化為整數類型,base表示的傳遞的字元串進位,預設是十進位class int(x=0)
print(len('abc')) #3 #返回一個對象的長度(或者元素的個數) #所謂的長度一般隻字符串,像整數、浮點數等數據類型沒有len方法len(s)
print(list([1, 2, 3])) #[1, 2, 3] prnt(list({'k1':'v1', 'k2':'v2'})) #['k2', 'k1'] #將一個可迭代對象轉化為列表 #可以看到字典只是把key組成了列表,因為字典真正迭代的是key,value只是與key對應而已class list([iterable])
s = map(lambda x: x**2, [1, 2, 3]) print(s) #<map object at 0x0000000002D14CF8> l = list(map(lambda x: x**2, [1, 2, 3])) print(l) #[1, 4, 9] #接收一個函數和一個可迭代對象,將可迭代對象里的每一個元素都做作為參數傳遞到函數中,並把函數的返回結果保存到一個map對象中 #函數可以是匿名函數,另外函數必須有返回值,如果沒有返回值,雖然不會報錯,但沒有任何意義,例如map(function, iterable, ...)
print(max(1, 2, 3)) #3 ''' max(iterable, *[, key, default]) max(arg1, arg2, *args[, key]) 返回可迭代對象中(或者2個以上參數中)最大的值 '''max
print(min(1, 2, 3)) #1 ''' min(iterable, *[, key, default]) min(arg1, arg2, *args[, key]) 返回可迭代對象中(或者2個以上參數中)最大的值 '''min
print(oct(9)) #'0o11' #將一個數轉化為8進位的表達形式 Python中0o表示8進位oct(x)
''' open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 打開文件並返迴文件文件對象,file表示文件名(可以是絕對路徑,也可以是相對路徑),mode表示打開方式,預設的是rt模式,表示只讀的文本格式 '''open
print(ord('a')) #97 #返回一個字元的Unicode編碼ord(c)
print(pow(2, 3) ) #8 print(pow(2, 3, 3)) #2 #如果只傳遞兩個參數x和y,就計算x的y次方,相當於x ** y #參數z表示將x ** y的結果對z取模,相當於x ** y % zpow(x,y[,z])
''' print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) 列印函數,object表示要輸出的對象,sep表示多個對象之間的分隔符,預設是空格,end表示末尾的字元,預設是回車符,file表示輸出的文件,預設為sys.stdout也就是終端(標準輸出) '''print
print(list(range(1, 10))) #[1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(range(1, 10, 2))) #[1, 3, 5, 7, 9] print(list(range(5)) #[0, 1, 2, 3, 4] ''' range(stop) range(start, stop[, step]) 生成大於等於start,小於stop步長為step的數字序列,start預設是0 '''range
print(reversed([0, 1, 2, 3, 4])) #<list_reverseiterator object at 0x7fcc954acd68> print(list(reversed([0, 1, 2, 3, 4]))) #[4, 3, 2, 1, 0] #翻轉一個序列,序列對象必須是有序的,也就是對象必須包含__reversed__()方法reversed(seq)
print(round(1.236, 2)) #1.24 print(round(1.2, 2)) #1.2 #返回一個浮點數的後面保留ndigits位小數的結果,四捨五入,小數點位數不足,不補0round(number[, ndigits])
print(set(1, 2, 4, 2)) #{1, 2, 4} #根據序列對象創建集合對象class set([iterable])
print(sorted(['A', 'b', 'c'])) #['A', 'b', 'c'] print(sorted(['A', 'b', 'C'])) #['A', 'C', 'b'] print(sorted(['A', 'b', 'C'], k