數(shù)據(jù)類型(補充) 上一部分
- 集合
- 時間日歷
函數(shù)
- 函數(shù)的參數(shù)
- 返回值
- 偏函數(shù)
- 高階函數(shù)
- 匿名函數(shù)
- 閉包
- 裝飾器
- 生成器
集合
無序的,不可隨機訪問的,不可重復(fù)的元素集合
- 與數(shù)學(xué)中的集合類似,可以進(jìn)行集合的交、并、差、補等操作。
- 分為可變集合和不可變集合
- set: 可以進(jìn)行增、刪、改操作
- frozenset: 創(chuàng)建好之后,無法再做修改。
可變集合的表示
# 直接表示
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}
# 集合推導(dǎo)
# 參考列表推導(dǎo)
s = {x for x in range(3)}
print(s) # {1, 0, 2}
不可變集合
# frozenset(iterable)
fs = frozenset("abc")
print(fs) # frozenset({'a', 'c', 'b'})
# 集合推導(dǎo)
fs = frozenset(x**2 for x in range(1, 6) if x % 2)
print(fs) # frozenset({1, 25, 9})
注意事項
- 創(chuàng)建空集合
# 錯誤做法 s = {} # 實際上構(gòu)建了一個空字典 s = set() # 空集合 - 集合中的元素必須是可哈希的值(不可變類型)。
- 集合中元素若出現(xiàn)重復(fù),則會被合并成一個。
# 多用于給列表元素進(jìn)行去重 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,不指定刪除元素,進(jìn)行隨機刪除;集合為空,報錯 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):
# 求交集,參數(shù)是可迭代類型 s1, s2 = {1, 2, 3, 4, 5}, {9, 8, 8, 5, 4} res = s1.intersection(s2) print(res) # {4, 5} # s1也可以是frozenset,返回結(jié)果也是frozenset # 可以使用邏輯運算符來完成 print(s1 & s2) # {4, 5} -
intersection_update(iterable)
# 更新調(diào)用該方法的對象 s1, s2 = {1, 2, 3, 4, 5}, {9, 8, 8, 5, 4} s1.intersection_update(s2) print(s1) # {4, 5} -
union(iterable):
# 求并集,參數(shù)是可迭代類型 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模塊
- 獲得當(dāng)前時間戳
# 獲得從 1970年1月1日到現(xiàn)在的時間秒數(shù) import time t = time.time() yearSpan = t / (60 * 60 * 24 * 365) print(yearSpan) # 48.6441059296045 - 獲得時間元組
# 根據(jù)所給的時間戳,返回當(dāng)時的時間信息 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) - 獲得格式化的時間
# 根據(jù)所給定的時間戳,返回一個更加可讀的時間 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 - 獲取當(dāng)前cpu時間
# 常用來統(tǒng)計一段代碼的執(zhí)行時間 import time # IDLE環(huán)境測試 start = time.clock() for i in range(0, 10) print(i, end=' ') end = time.clock() print(end - start) # 0.02806393769252448 - 休眠
# 線程休眠
# 每隔一秒打印一個數(shù)字
import time
n = 0
while True:
print(n)
time.sleep(1) # 參數(shù)單位是秒
datetiem模塊
模塊內(nèi)部有多個類:datetime、date、time。使用時選擇合適的類進(jìn)行操作就行了
- 獲取當(dāng)天的日期
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
函數(shù)
- 將一段代碼集中到一塊,起一個名字,下次可以根據(jù)這個名字再次使用這個代碼塊。
- 作用
- 方便代碼重用
- 分解任務(wù),簡化程序邏輯
- 使代碼更加模塊化
函數(shù)的參數(shù)
所有的傳參方式都是傳引用,注意列表做參數(shù)和數(shù)值做參數(shù)容易出現(xiàn)的問題。
單個參數(shù)
-
多個參數(shù)
# 定義方式 def funName(arg1, arg2, arg3...): # 調(diào)用方法 funName(arg1, arg2, arg3...) # 形參和實參一一對應(yīng) funName(arg2=v1, arg3=v3, arg1=v1) # 指明形參的名稱,不用嚴(yán)格按照順序 -
不定長參數(shù)
# 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 ... # 裝包,將傳入的參數(shù)裝入一個元組中,args就成了一個元組對象 # 拆包,將一個元組中的元素拆分出來,*args就成了參數(shù)序列 # 2. 利用字典的鍵值對 def myInfo(**args): print(type(args)) # <class 'dict'> # todo ... myInfo(name="rity", age=12) -
默認(rèn)參數(shù)
# 調(diào)用某些函數(shù)時,可以省略某些參數(shù),采用定義時指定的值 # 若不省略,則以調(diào)用時輸入的為準(zhǔn) def sorted(iterable, reverse=False): # todo... sorted([1, 3, 2, 5], reverse=True)
返回值
- 返回語句標(biāo)志著函數(shù)的結(jié)束,一個函數(shù)最好只有一處返回語句
- 如果想返回多個數(shù)據(jù),可以把數(shù)據(jù)包裝成一個集合,整體返回(列表,元組,字典...)
def funName():
# todo...
return data
偏函數(shù)
- 對于一個默認(rèn)值較多的函數(shù),有時我們需要重復(fù)用到其中的部分默認(rèn)值,每次指定默認(rèn)值比較麻煩。
- 可以將其中的默認(rèn)值先賦值好,然后封裝成一個新的函數(shù),這就是偏函數(shù)。
import functools
numStr = "100010"
res = int(numStr, base=2)
print(res) # 34
int2 = functools.partial(int, base=2) # 重新封裝,構(gòu)成偏函數(shù)
print(int2(numStr)) # 34
高階函數(shù)
- 一個函數(shù)的參數(shù)可以是另外一個函數(shù)
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
匿名函數(shù)
- lambda表達(dá)式
- 沒有名字的函數(shù)
res = (lambda x, y : x + y)(1, 2)
print(res) # 3
fun = lambda x, y : x + y
print(fun(2, 3)) # 5
# 更多的是配合 map(), reduce()等函數(shù)進(jìn)行使用
閉包
- 在函數(shù)嵌套定義的前提下
- 內(nèi)層函數(shù)引用了外層函數(shù)的變量
- 外層函數(shù)把內(nèi)層函數(shù)當(dāng)做返回值
def line_config(content, length):
define line():
print(content * length)
return line
line1 = line_config("-", 5);
line2 = line_config("*", 6)
line1(); # -----
line2(); # ******
- 作用域問題:內(nèi)層函數(shù)要修改外層函數(shù)的變量,要使用nonlocal進(jìn)行聲明,否則變量屬于內(nèi)層函數(shù)。
def test():
num = 10
def test2():
nonlocal num # test中的 num被修改
num = 666
return test2
- 當(dāng)內(nèi)層函數(shù)使用外層的變化量時,注意值得情況
def test():
funs = []
for i in range(1, 4):
def test2():
print(i)
funs.append(test2)
return funs
myFuns = test()
myFuns[0]() # 3 // 函數(shù)在運行時才會去確定變量的值
myFuns[1]() # 3 // 運行時,索引 i的值已經(jīng)發(fā)生變化了
myFuns[2]() # 3
裝飾器
- 在調(diào)用目標(biāo)函數(shù)之前,對這個函數(shù)對象進(jìn)行裝飾(增加一些其他功能)。
- 函數(shù)的名字不能改變。
- 函數(shù)體內(nèi)部的代碼不能發(fā)生改變。
def check(func):
def inner():
print("登錄驗證...")
func()
return inner()
# 在 fss()和 ftp()執(zhí)行之前,都會送入 check()進(jìn)行包裝
@check
def fss():
print("發(fā)說說")
# 上面三行等價于 fss = check(fss)
@check
def ftp():
print("發(fā)圖片")
# 上面三行等價于 ftp = check(ftp)
# 主業(yè)務(wù)邏輯如下:
flag = 1
if flag == 1:
fss() # 登錄驗證...
else: # 發(fā)說說
ftp()
- 多個裝飾器的調(diào)用順序
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()
# 運行結(jié)果 //從下到上裝飾,從上到下執(zhí)行,分析略
# 裝飾的過程就相當(dāng)于你把一件禮物一層一層的進(jìn)行包裝,先包裝內(nèi)層
# 執(zhí)行的過程就是把禮物拆開,最外面的包裝先被拆開
----a----
----1----
----2----
----b----
----3----
- 對帶有參數(shù)的函數(shù)進(jìn)行裝飾
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
- 對帶有返回值的函數(shù)進(jìn)行裝飾
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)
- 帶有參數(shù)的裝飾器
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
生成器
- 是一個特殊的迭代器
- 特性:
- 惰性計算數(shù)據(jù),節(jié)省內(nèi)存
- 能夠記錄狀態(tài),通過
next()函數(shù),訪問下一個狀態(tài)
- 使用方式
# 生成器表達(dá)式
l = (i for i in range(1, 10000000) if i % 2)
print(type(l)) # <class 'generator'> // 不是元組推導(dǎo),沒有元組推導(dǎo)式
print(next(l)) # 1
print(next(l)) # 3
for i in l:
print(i) # 循環(huán)打印出所有滿足條件的值
# 生成器函數(shù)
def test():
for i in range(1, 9):
yield i
g = test()
print(next(g)) # 1
print(next(g)) # 2