單元素元祖:
a = (1) # 這是整數1
a = (1,) # 這纔是元祖
也許這兩行,大家當時疑惑過,而且如今也都知道了,固然重點並不在這裏。。
我無聊的時候想過,爲何單元素元祖要這樣設計 -> (1,)?
很少廢話,看下面代碼,本身理解:
a = (3,)
a = (3)
a = (1+2)
a = (1+2,)
a = (1+2) + (3+4)
a = (1+2,) + (3+4,)
注:
這是我我的原創理解的一個微不足道的知識點,可是印象卻特別深入。
由於我反向推測出 設計者爲何會設計出這種語法。
(固然,也許個人推測和設計者當時的想法的並不同~~~手動滑稽)
深/淺拷貝-copy/deepcopy(皮/肉)
"""
最開始接觸深淺拷貝的時候沒太大感受,只是普通的以爲避免數據污染就夠了
後來有一次用scrapy寫爬蟲的時候,層次太多致使內存有些頂不住。
後來用的 deepcopy() 來 優化 scrapy 的 meta, 雖然效果不是特別明顯,可是感受深淺拷貝頗有用
"""
1. =號,不拷貝
=號就意味着,引用指向同一個地址空間,‘敵動我動,敵不動我不懂’ 的感受。 LOL一句話:"連體嬰兒"~~
2. copy:也稱淺拷貝
我用最簡單的話解釋一下:淺拷貝就是隻能拷貝最外面的一層皮,來獨立開闢空間使用,再深仍是共用的
eg:
from copy import copy
from copy import deepcopy
a = [[1,2,3],[4,5,6]]
b = deepcopy(a)
b[0] = 0 # 這就是最外面的一層皮
print(b)
print(a)
3. deepcopy:顧名思義了,深拷貝
若是你聽懂我上面的話,我感受這個就更好理解了, 淺拷貝是皮,深拷貝那就是肉了唄。
沒錯,不管套了幾層的序列結構,每一層都是獨立開闢空間,獨立指向。
from copy import copy
from copy import deepcopy
a = [[1,2,3],[4,5,6]]
b = deepcopy(a)
b[0][1] = 0 # 看清楚,這回就是裏面的肉了, 深拷貝:你改哪裏都行,哪裏都與我無關
print(b)
print(a)
lambda黑科技
"""lambda至關於匿名函數,可使代碼簡介,但有時也會被人唾棄,但我仍然喜歡用lambda"""
1. 試想:若是你想在lambda調用多個函數,該如何寫?
lambda: (print(1),print(2)) # 最外層加個括號便可
2. 若是你想讓這個 lambda函數直接自執行,而不是經過賦予一個函數引用再執行?
1. 這個也是我本身瞎鼓搗出來的。
2. 雖然我JS水平很垃圾,可是我知道JS匿名函數有一種執行方式叫作 ‘自執行’。
3. 把上面類比一下。
看吧,這就是Python版的匿名函數自執行方法。
Python版本: (lambda a:print(a))(1)
JS版: (function(){})()
lambda的虛僞替代品-operator
"""
聽說這個模塊能夠替代lambda, 我的理解此模塊並不那麼太有實用價值,理解成本也偏高,
建議:若是不喜歡lambda或者lambda用的不多的人,能夠研究一下此模塊。此模塊的意圖仍是能夠的。
我仍是喜歡使用 lambda
"""
直接上個例子:(字典基於Value來排序)
傳統lambda寫法:
In [27]: a = {'1':6, '2':5, '3':4}
In [28]: sorted(a.items(), key=lambda a:a[1]) # 看key= 這裏
Out[28]: [('3', 4), ('2', 5), ('1', 6)]
operator寫法:
from operator import itemgetter
In [25]: a = {'1':6, '2':5, '3':4}
In [26]: sorted(a.items(), key=itemgetter(1)) # 就是key= 這裏有區別
Out[26]: [('3', 4), ('2', 5), ('1', 6)]
若是上面兩種新舊方法都很模糊,那麼我再解釋一下: 我認爲上面能讓人頭疼的也就是 索引 1 了!!!!
sorted, map這種高階函數,我以前也單獨講過,它會把 一個序列的每個元素用管道函數進行映射。
sorted稍微特殊一點,它的管道函數方法變成了key=這裏: (變相理解爲 指定排序的基準/參考)
1. key=lambda a:a[1]
指定基準:序列a的 每子元素 的 第1號索引子元素 # eg: [[1,2],[3,4],[5,6]] 就是2,4,6
2. key=itemgetter(1)
指定基準:同上如出一轍,只不過寫法不同,邏輯步驟就是 原本來本從 lambda那裏演變過來的。
總結與我的觀點:
1. operator 模塊只是 lambda 使用思想 的 高一層的封裝
2. 讓使用者能夠忽略lambda格式細節
3. 可是我認爲 若是lambda都用很差, 那麼 這個 itemgetter(1) 這種子元素 索引的指定 也會很困難
4. 因此我仍是建議用 lambda, 當你 lambda思想練熟了以後, 用 operator看看官方文檔就是很快的事情
封包/拆包(解構賦值)/函數佔位參數騷操做
"""
再次說明一下:我寫的全部的都是Py3的/ Py2的解構賦值可能有些出入,此處我只說Py3
"""
封包:
1)
def f(a,*b):
print(a) # 1
print(b) # (2,3,4)
f(1,2,3,4)
2)
def f(**kwargs):
print(kwargs) # {'a': 3, 'b': 4}
f(**dict(a=3,b=4))
拆包(解構賦值):
"""
我說過太屢次了, ES6的語法和Python很像。解構賦值這個詞也是從ES6聽到的。
不過ES6的解構,還能夠解構 {} 和 解構空值 和 解構默認值, 而Python不能夠
"""
1) 只要第一個
a, *_ = range(5)
print(a, _) # 0 [1, 2, 3, 4]
2) 只要第一個和最後一個
a, *_, c = range(5)
print(a, _, c) # 0 [1, 2, 3] 4
3) 只要最後一個
*_, b = range(5)
print(_, b) # [0, 1, 2, 3] 4
函數佔位參數騷操做:
"""
這是我在源碼中看到的,當時以爲很驚訝,本身試了一下,下面說下本身的理解:
這個*的做用就是: (*後面的參數是 調用時 必須命名 且 必須傳遞 的參數)
a你必須給我傳過來,可是你不寫 a=
b你必須給我傳過來,可是你必須寫 b=
"""
def f(a,*,b):
print(a)
print(b)
f(1,b=3) # f(a=1,b=3) # 只能經過這兩種方式調用
反射-getattr & setattr & hasattr & delattr & import_module
綜合例子:
from importlib import import_module
random = import_module('random') # 動態反射導入模塊
# 或 random = __import__('random')
if hasattr(random, 'randint'): # 檢測模塊中是否有函數
randint = getattr(random,'randint') # 動態反射導入函數
print(eval('randint(0,1)')) # 字符串轉語句執行(相似反射)
getattr & setattr & hasattr & delattr 講解:
hasattr & getattr
random = __import__('random')
if hasattr(random,'randint'): # 檢測 random 模塊中是否有 randint 函數
randint = getattr(random,'randint')
print(randint(0,1))
delattr & hasattr
delattr(random, 'randint') # 動態刪除模塊中的 randint函數
if not hasattr(random,'randint'):
print('沒有此函數了,讓delattr刪除了')
setattr & getattr # 動態從新設置模塊的 randint函數,並給個函數體
setattr(random, 'randint', lambda:print('設置這個方法湊合用把。'))
randint = getattr(random, 'randint')
randint()
模塊從新導入到內存-reload
from imp import reload
import time
reload(time)
print(time.time())
進度條-tqdm
for x in tqdm(range(100)):
import time
time.sleep(1)
print(x)
tqdm包裝一個可迭代對象, 只是裝飾了一下,使用方法仍是像原來同樣使用。
票數統計-Counter
In [2]: from collections import Counter
In [3]: Counter([1,2,3,4])
Out[3]: Counter({1: 1, 2: 1, 3: 1, 4: 1})
In [4]: Counter([1,1,1,2,2,3]) # 統計頻次
Out[4]: Counter({1: 3, 2: 2, 3: 1})
In [5]: Counter([1,1,1,2,2,3]).most_common(1) # 頻次最多的前1個
Out[5]: [(1, 3)]
文件 複製/移動-shutil
import shutil
shutil.copy(源,目標) # 複製
shutil.move(源,目標) # 移動,更名
shutil.rmtree(r'目錄名') # 刪除目錄(級聯刪除) # 參數只能是目錄
文件遍歷-os.walk
"""
os.walk() 是一個深度遍歷模式的文件遍歷函數
返回值是一個迭代器,遍歷這個迭代器後,每一次的返回值都是以下順序三種構成
1. current_path: 當前路徑
2. dir_list: 其下目錄列表
3. file_list: 其下文件列表
"""
import os
file_generator = os.walk('D:/虛擬E盤-代碼空間/TF2')
for current_dir, dir_list, file_list in file_generator:
print(current_dir, dir_list, file_list)
非阻塞執行cmd/shell-subprocess
"""
主要代替os.system
"""
import subprocess
res = subprocess.run('dir', shell=True, stdout=subprocess.PIPE) # 結果輸入到res管道中去
print(res.stdout.decode('gbk')) # res管道中有輸出日誌,若是在win下,須要 decode
排列組合-itertools模塊
import itertools
list(itertools.product([1,2,3],repeat=3)) # 複製3份有序全排列, repeat=3
list(itertools.permutations([1,2,3], 3)) # 內部有序排列, 3表示最後排列爲幾位
list(itertools.permutations([1,2,3,4],3)) # 無序組合, 3表示3位
枚舉-emunerate
In [100]: list(enumerate(list('abcde'),start=1)) # 默認從0,開始標號, start=1就從1開始
Out[100]: [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]
In [108]: list(enumerate(((1,2),(3,4))))
Out[108]: [(0, (1, 2)), (1, (3, 4))]
In [106]: list(enumerate({"a":'c','b':'d'}))
Out[106]: [(0, 'a'), (1, 'b')]
global & nonlocal & globals() & locals()
global: 函數外的變量只能在函數內部取值,而不能修改, 若是想要在函數內部修改外部變量, ‘global 變量名’ 便可
a = 1
def f():
global a
a += 1
print(a)
f()
nonlocal: 原理同上如出一轍,只不過應用場景是閉包了,代碼以下:
def f():
a = 1
def f1():
nonlocal a
a = a+1
print(a)
f1()
f()
日曆-calendar
import calendar
calendar.calendar(2019) # 返回2019年的日曆
calendar.month(2919,5) # 返回2019年5月的日曆
calendar.isleap(2000) # 判斷2000年是否爲閏年
時間/日期-time/datetime
import time
1. 時間戳:
time.time()
2. 字符串轉時間(p-pass方便記憶)
from datetime import datetime
fordate = datetime.strptime('2019-5-25 9:30:30', '%Y-%m-%d %H:%M:%S')
print(fordate)
3. 時間轉字符串(f-from方便記憶)
from datetime import datetime
strdate = datetime.strftime(fordate, '%Y-%m-%d %H:%M:%S')
print(strdate)
4. 初始化時間
from datetime import datetime
dt1 = datetime(2019,5,25,9,37) # 初始化時間爲 datetime格式
dt1 = datetime.now() # 獲取當前時間爲 datetime格式
print(dt1.year)
print(dt1.month)
print(dt1.day)
print(dt1.hour)
print(dt1.minute)
print(dt1.second)