資料型別(補充) [上一部分]
* 集合
* 時間日歷
函式
* 函式的引數
* 回傳值
* 偏函式
* 高階函式
* 匿名函式
* 閉包
* 裝飾器
* 生成器
#### 集合
**無序的**,**不可隨機訪問的**,**不可重復**的元素集合
* 與數學中的集合類似,可以進行集合的**交、并、差、補**等操作,
* 分為**可變集合**和**不可變集合**
* set: 可以進行**增、刪、改**操作
* frozenset: 創建好之后,無法再做修改,
##### 可變集合的表示
```
# 直接表示
s = {1, 2, 3, 4}
print(s, type(s)) # {1, 3, 4, 2} <class 'set'>
# set(Iterable)
s1 = set("abc")
s2 = set([1, 2, 3])
print(s1, s2) # {'a', 'b', 'c'} {1, 2, 3}
# 集合推導
# 參考串列推導
s = {x for x in range(3)}
print(s) # {1, 0, 2}
```
##### 不可變集合
```
# frozenset(iterable)
fs = frozenset("abc")
print(fs) # frozenset({'a', 'c', 'b'})
# 集合推導
fs = frozenset(x**2 for x in range(1, 6) if x % 2)
print(fs) # frozenset({1, 25, 9})
```
##### 注意事項
* 創建空集合
```
# 錯誤做法
s = {} # 實際上構建了一個空字典
s = set() # 空集合
```
* 集合中的元素必須是**可哈希**的值(不可變型別),
* 集合中元素若出現重復,則會被合并成一個,
```
# 多用于給串列元素進行去重
li = {1, 2, 2, 3, 3}
li = list(set(li))
print(li) # [1, 2, 3]
```
##### 集合的操作
* 單集合操作
```
s = {1, 2, 3}
#-----------------------------------------
# 新增元素
# 1.集合可變 2.新增元素可哈希
s.add(4)
print(s) # {1, 3, 2, 4}
#-----------------------------------------
# 洗掉元素
# 1.remove(element)
# 洗掉指定的元素,若無該元素,報錯
s.remove(2)
print(s) # {1, 3}
# 2.discard(element)
# 洗掉指定的元素,若無該元素,pass
s.discard(2)
print(s) # {1, 3}
s.discard(666)
print(s) # {1, 3}
# 3.pop(element)
# 洗掉并回傳指定元素,若無該元素,報錯
# 省略 element,不指定洗掉元素,進行隨機洗掉;集合為空,報錯
s.pop(1)
print(s) # {2, 3}
s.pop()
print(s) # {2}
s.pop()
print(s) # set() //空集合的意思
# 4.clear()
# 清空集合,集合依然存在
s.clear()
print(s) # set()
#-----------------------------------------
# 遍歷集合
# 1.for in
for v in s:
print(s, sep=' ') # 1 2 3
# 2.迭代器
its = iter(s)
print(next(its)) # 1
print(next(its)) # 2
print(next(its)) # 3
```
* 多集合操作
* **intersection(iterable)**:
```
# 求交集,引數是可迭代型別
s1, s2 = {1, 2, 3, 4, 5}, {9, 8, 8, 5, 4}
res = s1.intersection(s2)
print(res) # {4, 5}
# s1也可以是frozenset,回傳結果也是frozenset
# 可以使用邏輯運算子來完成
print(s1 & s2) # {4, 5}
```
* **intersection_update(iterable)**
```
# 更新呼叫該方法的物件
s1, s2 = {1, 2, 3, 4, 5}, {9, 8, 8, 5, 4}
s1.intersection_update(s2)
print(s1) # {4, 5}
```
* **union(iterable)**:
```
# 求并集,引數是可迭代型別
s1, s2 = {1, 2, 3}, {2, 3, 4}
res = s1.union(s2)
print(res) # {1, 2, 3, 4}
# 可以使用邏輯運算子來完成
print(s1 | s2) # {1, 2, 3, 4}
```
* **update(iterable)**
```
s1, s2 = {1, 2, 3}, {2, 3, 4}
s1.update(s2)
print(s1) # {1, 2, 3, 4}
```
* **difference(iterable)**
```
# 求差集
s1, s2 = {1, 2, 3}, {2, 3, 4}
res = s1.difference(s2)
print(res) # {1}
# 邏輯運算子
print(s1 - s2) # {1}
```
* **difference_update(iterable)**:
```
s1, s2 = {1, 2, 3}, {2, 3, 4}
s1.difference_update(s2)
print(s1) # {1}
```
* **判定操作**
```
# isdisjoint() 兩個集合是否不相交
# isuperset() 一個集合是否包含另一個集合
# issubset() 一個集合是否包含于另一個集合
```
#### 時間日歷
##### time模塊
* 獲得當前時間戳
```
# 獲得從 1970年1月1日到現在的時間秒數
import time
t = time.time()
yearSpan = t / (60 * 60 * 24 * 365)
print(yearSpan) # 48.6441059296045
```
* 獲得時間元組
```
# 根據所給的時間戳,回傳當時的時間資訊
import time
t = time.time()
res = localtime(t)
print(res) # time.struct_time(tm_year=2018, tm_mon=8, tm_mday=12, tm_hour=10, tm_min=22, tm_sec=4, tm_wday=6, tm_yday=224, tm_isdst=0)
```
* 獲得格式化的時間
```
# 根據所給定的時間戳,回傳一個更加可讀的時間
import time
t = time.time()
res = time.ctime(t)
print(res) # Sun Aug 12 10:33:58 2018
```
* 獲得格式化的時間字串
```
# time.strftime(格式字串, 時間元組)
res = time.strftime("%y-%m-%d %H:%M:%S", time.localtime())
print(res) # 18-08-12 10:39:28
res = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(res) # 2018-08-12 10:39:50
```
* 獲取當前cpu時間
```
# 常用來統計一段代碼的執行時間
import time
# IDLE環境測驗
start = time.clock()
for i in range(0, 10)
print(i, end=' ')
end = time.clock()
print(end - start) # 0.02806393769252448
```
* 休眠
```
# 執行緒休眠
# 每隔一秒列印一個數字
import time
n = 0
while True:
print(n)
time.sleep(1) # 引數單位是秒
```
##### datetiem模塊
模塊內部有多個**類**:**datetime**、**date**、**time**,使用時選擇合適的類進行操作就行了
* 獲取當天的日期
```
import datetime
t = datetime.datetime.now()
print(type(t)) # <class 'datetime.datetime'>
print(t) # 2018-08-12 11:04:12.982890
print(t.year) # 2018
print(t.month) # 8
```
* 計算n天之后的日期
```
import datetime
t = datetime.datetime.today()
res = t + datetime.timedelta(days=7)
print(t, res, sep='|') # 2018-08-12 11:10:31.995501|2018-08-19 11:10:31.995501
```
* 獲得兩個日期的時間差
```
import datetime
first = datetime.datetime(2018, 9, 10, 12, 0, 0)
second = datetime.datetime(2018, 10, 1, 0, 0, 0)
res = second - first
print(res) # 20 days, 12:00:00
```
#### 函式
* 將一段代碼集中到一塊,起一個名字,下次可以根據這個名字再次使用這個代碼塊,
* 作用
* 方便代碼重用
* 分解任務,簡化程式邏輯
* 使代碼更加模塊化
##### 函式的引數
所有的傳參方式都是傳**參考**,注意**串列**做引數和**數值**做引數容易出現的問題,
* 單個引數
* 多個引數
```
# 定義方式
def funName(arg1, arg2, arg3...):
# 呼叫方法
funName(arg1, arg2, arg3...) # 形參和實參一一對應
funName(arg2=v1, arg3=v3, arg1=v1) # 指明形參的名稱,不用嚴格按照順序
```
* 不定長引數
```
# 1\. 利用元組的拆包裝包
def mySum(*args):
print(type(args)) # <class 'tuple'>
print(args) # (1, 2, 3, 4)
print(*args) # 拆包操作 1, 2, 3, 4
for v in args:
# todo ...
# 裝包,將傳入的引數裝入一個元組中,args就成了一個元組物件
# 拆包,將一個元組中的元素拆分出來,*args就成了引數序列
# 2\. 利用字典的鍵值對
def myInfo(**args):
print(type(args)) # <class 'dict'>
# todo ...
myInfo(name="rity", age=12)
```
* 默認引數
```
# 呼叫某些函式時,可以省略某些引數,采用定義時指定的值
# 若不省略,則以呼叫時輸入的為準
def sorted(iterable, reverse=False):
# todo...
sorted([1, 3, 2, 5], reverse=True)
```
##### 回傳值
* 回傳陳述句標志著函式的結束,一個函式最好只有一處回傳陳述句
* 如果想**回傳多個資料**,可以把資料包裝成一個集合,整體回傳(串列,元組,字典...)
```
def funName():
# todo...
return data
```
##### 偏函式
* 對于一個默認值較多的函式,有時我們需要重復用到其中的部分默認值,每次指定默認值比較麻煩,
* 可以將其中的默認值先賦值好,然后封裝成一個新的函式,這就是偏函式,
```
import functools
numStr = "100010"
res = int(numStr, base=2)
print(res) # 34
int2 = functools.partial(int, base=2) # 重新封裝,構成偏函式
print(int2(numStr)) # 34
```
##### 高階函式
* 一個函式的引數可以是另外一個函式
```
def calculate(a, b, cal_fun):
print(cal_fun(a, b))
def sum(a, b):
return a + b
def sub(a, b):
return a - b
calculate(2, 3, sum) # 5
calculate(2, 3, sub) # -1
```
##### 匿名函式
* lambda運算式
* 沒有名字的函式
```
res = (lambda x, y : x + y)(1, 2)
print(res) # 3
fun = lambda x, y : x + y
print(fun(2, 3)) # 5
# 更多的是配合 map(), reduce()等函式進行使用
```
##### 閉包
* 在函式嵌套定義的前提下
* 內層函式參考了外層函式的變數
* 外層函式把內層函式當做回傳值
```
def line_config(content, length):
define line():
print(content * length)
return line
line1 = line_config("-", 5);
line2 = line_config("*", 6)
line1(); # -----
line2(); # ******
```
* 作用域問題:內層函式要修改外層函式的變數,要使用**nonlocal**進行宣告,否則變數屬于內層函式,
```
def test():
num = 10
def test2():
nonlocal num # test中的 num被修改
num = 666
return test2
```
* 當內層函式使用外層的變化量時,注意值得情況
```
def test():
funs = []
for i in range(1, 4):
def test2():
print(i)
funs.append(test2)
return funs
myFuns = test()
myFuns[0]() # 3 // 函式在運行時才會去確定變數的值
myFuns[1]() # 3 // 運行時,索引 i的值已經發生變化了
myFuns[2]() # 3
```
##### 裝飾器
* 在呼叫目標函式之前,對這個函式物件進行**裝飾**(增加一些其他功能),
* 函式的**名字不能改變**,
* 函式體內部的**代碼不能發生改變**,
```
def check(func):
def inner():
print("登錄驗證...")
func()
return inner()
# 在 fss()和 ftp()執行之前,都會送入 check()進行包裝
@check
def fss():
print("發說說")
# 上面三行等價于 fss = check(fss)
@check
def ftp():
print("發圖片")
# 上面三行等價于 ftp = check(ftp)
# 主業務邏輯如下:
flag = 1
if flag == 1:
fss() # 登錄驗證...
else: # 發說說
ftp()
```
* 多個裝飾器的呼叫順序
```
def one(func):
print('----1----')
def two():
print('----2----')
func()
return two
def a(func):
print('----a----')
def b():
print('----b----')
func()
return b
@one
@a
def demo():
print('----3----')
demo()
# 運行結果 //從下到上裝飾,從上到下執行,分析略
# 裝飾的程序就相當于你把一件禮物一層一層的進行包裝,先包裝內層
# 執行的程序就是把禮物拆開,最外面的包裝先被拆開
----a----
----1----
----2----
----b----
----3----
```
* 對**帶有引數**的函式進行裝飾
```
def zsq(funcs):
def inner(*args, **kwargs): # 裝包
print("-" * 5)
func(*args, **kwargs) # 拆包
return inner
@zsq
def fun1(n1, n2, n3):
print(n1, n2, n3)
@zsq
def fun2(n):
print(n)
fun1(1, 2, n3=8) # 1 2 8
fun2(3) # 3
```
* 對帶**有回傳值的**函式進行裝飾
```
def zsq(funcs):
def inner(*args, **kwargs): # 裝包
print("-" * 5)
res = func(*args, **kwargs) # 拆包
return res
@zsq
def fun1(n1, n2, n3):
return sum(n1, n2, n3)
fun1(1, 2, 3)
```
* 帶有引數的裝飾器
```
def getzsq(char):
def zsq (func):
def inner():
print(char * 5)
func()
return inner
return zsq
@getzsq("*")
def f(): # *****
print("666") # 666
@getzsq("-")
def f1(): # -----
print("666") # 666
```
##### 生成器
* 是一個特殊的迭代器
* 特性:
* 惰性計算資料,節省記憶體
* 能夠記錄狀態,通過`next()`函式,訪問下一個狀態
* 使用方式
```
# 生成器運算式
l = (i for i in range(1, 10000000) if i % 2)
print(type(l)) # <class 'generator'> // 不是元組推導,沒有元組推導式
print(next(l)) # 1
print(next(l)) # 3
for i in l:
print(i) # 回圈列印出所有滿足條件的值
# 生成器函式
def test():
for i in range(1, 9):
yield i
g = test()
print(next(g)) # 1
print(next(g)) # 2
```
#####推薦一下我建的python學習交流扣扣qun:850973621,群里有免費的視頻教程,開發工具、
#####電子書籍、專案原始碼分享,一起交流學習,一起進步!

作者:MetaT1an
鏈接:https://www.jianshu.com/p/ba8b9bdea10a
來源:簡書
著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/232298.html
標籤:Python
上一篇:python實戰筆記(二)
