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)) #輸出10

print(all([1, True, 1 == 1])) #True

print(any([None, "", [], (), {}, 0, False])) #False print(any([None, "", [], (), {}, 0, True]) )#True #通常情況下“空”(None,空字符串、空列表,0等等)都是表示False

print(bin(10)) #'0b1010'

print(bool()) #False print(bool(10)) #True

print(chr(89999)) #'\U00015f8f' print(chr(97)) #'a'

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

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']

print(divmod(10, 3)) #(3, 1) 返回兩個數的得商和余數組成的元組,相當於(a // b, a % b)

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')]

print(eval('3 + 4 * (1 - 3)')) #-5 #將的字符串形式的算數表達式進行計算,並返回結果

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] '''

print('0.5') #0.5 print(0.5) #0.5 #創建一個浮點類型的對象

#返回某個對象的幫助信息

print(hex(23)) #'0x17' #返回一個整數的16進制表達式

print(id(1)) #10455040 #返回對象的id(可以理解為Python為每個對象的編號,或者理解為是Python對象內存地址的表達形式)

s = input('python>>') print(s) ''' 輸入123 輸出'123' 接受用戶從控制台的輸入,並將用戶輸入的信息,以字符串的返回,prompt表示輸入時前顯示的字符串 '''

print(int()) #0 print(int('1010', base=2)) #10 #創建一個整數類型的對象,默認如果創建的0,如果傳遞的是字符串類型的,可以把字符串表達式所表示的整數轉化為整數類型,base表示的傳遞的字符串進制,默認是十進制

print(len('abc')) #3 #返回一個對象的長度(或者元素的個數) #所謂的長度一般只字符串,像整數、浮點數等數據類型沒有len方法

print(list([1, 2, 3])) #[1, 2, 3] prnt(list({'k1':'v1', 'k2':'v2'})) #['k2', 'k1'] #將一個可迭代對象轉化為列表 #可以看到字典只是把key組成了列表,因為字典真正迭代的是key,value只是與key對應而已

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對象中 #函數可以是匿名函數,另外函數必須有返回值,如果沒有返回值,雖然不會報錯,但沒有任何意義,例如

print(max(1, 2, 3)) #3 ''' max(iterable, *[, key, default]) max(arg1, arg2, *args[, key]) 返回可迭代對象中(或者2個以上參數中)最大的值 '''

print(min(1, 2, 3)) #1 ''' min(iterable, *[, key, default]) min(arg1, arg2, *args[, key]) 返回可迭代對象中(或者2個以上參數中)最大的值 '''

print(oct(9)) #'0o11' #將一個數轉化為8進制的表達形式 Python中0o表示8進制

''' open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 打開文件並返回文件文件對象,file表示文件名(可以是絕對路徑,也可以是相對路徑),mode表示打開方式,默認的是rt模式,表示只讀的文本格式 '''

print(ord('a')) #97 #返回一個字符的Unicode編碼

print(pow(2, 3) ) #8 print(pow(2, 3, 3)) #2 #如果只傳遞兩個參數x和y,就計算x的y次方,相當於x ** y #參數z表示將x ** y的結果對z取模,相當於x ** y % z

''' print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) 打印函數,object表示要輸出的對象,sep表示多個對象之間的分隔符,默認是空格,end表示末尾的字符,默認是回車符,file表示輸出的文件,默認為sys.stdout也就是終端(標准輸出) '''

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

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__()方法

print(round(1.236, 2)) #1.24 print(round(1.2, 2)) #1.2 #返回一個浮點數的后面保留ndigits位小數的結果,四舍五入,小數點位數不足,不補0

print(set(1, 2, 4, 2)) #{1, 2, 4} #根據序列對象創建集合對象

print(sorted(['A', 'b', 'c'])) #['A', 'b', 'c'] print(sorted(['A', 'b', 'C'])) #['A', 'C', 'b'] print(sorted(['A', 'b', 'C'], key = lambda x: x.lower()))#['A', 'b', 'C'] print(sorted(['A', 'b', 'C'], key = lambda x: x.lower(), reverse = True)) #['C', 'b', 'A'] #對一個序列對象進行排序,key接收一個函數,將序列的每一個函數處理返回的結果作為排序的依據,比如字符串都轉換成小寫排序或字典按照key或value排序等,reverse表示對排序的結果是否排序,默認字符串是先大寫后小寫的順序排序的

print(str('abc')) #'abc' print(str(1234)) #'1234' #創建一個字符串對象,或者將一個對象轉化為字符串對象

print(sum([1, 2, 4])) #7 print(sum([1, 2, 4], 1)) #8 #返回一個序列對象的相加的總和在加上start,start默認是0,序列對象要么全是數字要么都是字符串,字符串就相當於把它們都拼接在一起

print(tuple()) #() print(tuple([1, 2, 4])) #(1, 2, 4) #創建一個元組對象,或將一個對象轉化為元組

print(type(1)) #<class 'int'> ''' class type(object) class type(name, bases, dict) 返回一個對象的類型 '''

import sys vars(sys) #{'version_info': sys.version_info(major=3, minor=4, micro=0, releaselevel='final', serial=0), 'getswitchinterval': <built-in function getswitchinterval>, '__name__': 'sys', 'path_hooks': [<class 'zipimport.zipimporter'>, <function FileFinder.path_hook.<locals>.path_hook_for_FileFinder at 0x7fcc97b51ae8>],后面省略n多行 #返回模塊,類,實例或者任何其他有__dict__屬性的對象的__dict__屬性,默認是顯示當前環境的

x = [1, 2, 3, 4] y = ['a', 'b', 'c'] print(zip(x, y)) #<zip object at 0x7fcc954aea08> print(list(zip(x, y))) #[(1, 'a'), (2, 'b'), (3, 'c')] #將多個元素組成一個新的zip對象,zip對象的元素個數取決於元素最少的參數