day05_雷神_函數進階
#day05
1、叠代器
1.1可叠代對象
str,list,tuple,dict,set,range,文件句柄 等都是可叠代對象
第一種方法:在該對象中,含有__iter__方法的就是可叠代對象,遵循可叠代協議。
print(dir(str))
dir() 打印出str對象的所有方法。
print(‘__iter__‘ in dir(list))
返回值: True 說明是可叠代對象
第二種方法: isinstance("123",Iterable)
from collections import Iterable (需要import Iterable) a = isinstance("[1,2,3]", Iterable) print(a)
1.2叠代器
內部含有__iter__ 且含有__next__方法的對象就是叠代器,遵循叠代器協議。
將可叠代對象轉換為叠代器(兩種方法)
s1 = "abc" obj_s1 = iter(s1) #方法一 obj_s1 = s1.__iter__() #方法二 print(obj_s1) 結果:<str_iterator object at 0x000002370C657390> 叠代器只能通過__next__方法來讀取值: print(obj_s1.__next__()) # a print(obj_s1.__next__()) # b print(obj_s1.__next__()) # c print(obj_s1.__next__()) # 報錯:StopIteration
判斷是否是叠代器的方法一:
s1 = "asd"
print(‘__iter__‘ in dir(s1)) #True
print(‘__next__‘ in dir(s1)) #False
obj_s1 = iter(s1)
print(‘__iter__‘ in dir(obj_s1)) #True
print(‘__next__‘ in dir(obj_s1)) #True
方法二:
s1 = "asd" obj_s1 = iter(s1) print(isinstance(s1,Iterator)) #False print(isinstance(obj_s1,Iterator)) #True
叠代器的好處
節省內存
惰性機制
單向不可逆
1.3生成器
生成器的本質就是叠代器,他是自定義的叠代器(用Python寫的)。
- 函數的方式構建一個生成器:
示例1:
def func1():
print(111)
yield 222
print(333)
print(444)
obj_1 = func1() # g_obj = func1() # 生成器對象
# 凡是函數中見到yield 他就是生成器
print(obj_1)
print(obj_1.__next__()) # 111, 222 一個next對應一個yield,一一對應
print(obj_1.__next__()) # 報錯StopIteration
示例2:
def cloth():
for i in range(1,5001):
yield ‘衣服%s‘ %i
g_obj = cloth() #生成器對象
print(g_obj) #<generator object cloth at 0x0000020ADFBCDE08>
for i in range(1,51):
print(g_obj.__next__()) # 先來50套
for i in range(1,101):
print(g_obj.__next__()) # 再加100套,從50到了150套,因為叠代器單向不可逆
send
send和next都是對生成器取值,每一個都要對應一個yield,send 會給上一個yield 發送一個值。
send 不能用在第一次取值。最後一個yield 不能得到值
def func1():
count = yield 666
print(count)
yield 777
yield 888
g_obj = func1()
print(g_obj.__next__())
# print(g_obj.__next__())
# 666
# None
# 777
print(g_obj.send(‘taibai‘))
# 666
# taibai
# 777
# print(g_obj.send(‘alex‘)) # 相當於給yield 777 整體賦值為"alex",只是沒有打印
2、列表推導式(生成器表達式)
遍歷模式 l = [ i for i in range(1,11)]
[ (結果需要的變量形式)變量 for 變量 in iterable ]
[變量(加工後的變量) for 變量 in iterable] 遍歷模式
l2 = [‘python%s期‘ % i for i in range(1,23)]
print(l2)
[變量(加工後的變量) for 變量 in iterable if 條件] 篩選模式
l2 = [i for i in range(1,31) if i % 3 == 0]
print(l2)
l2_obj = (i for i in range(1,31) if i % 3 == 0) #將[]換成()就是生成器表達式了。
print(l2_obj)
print(l2_obj.__next__())
print(l2_obj.__next__())
li = ["a","c",‘houbinglei‘,‘alex‘]
l = [i.upper() for i in li if len(i)>=3 ]
print(l)
區別
# 列表推導式:簡單,一行搞定。
# 特別復雜的數據列表推導式無法實現,只能用其他方式實現。
# 列表推導式不能排錯。
# 列表推導式與生成器表達式區別
# 1 ,列推直觀能看出,但是占內存
# 2,生成器表達式不易看出,但是節省內存。
示例:-
x = {
‘name‘:‘alex‘,
‘Values‘:[{‘timestamp‘:1517991992.94,
‘values‘:100,},
{‘timestamp‘: 1517992000.94,
‘values‘: 200,},
{‘timestamp‘: 1517992014.94,
‘values‘: 300,},
{‘timestamp‘: 1517992744.94,
‘values‘: 350},
{‘timestamp‘: 1517992800.94,
‘values‘: 280}
],}
li = [[i[‘timestamp‘],i[‘values‘]] for i in x[‘Values‘] ]
print(li)
關鍵:從要的數據類型分析出規律。
字典推導式
將一個字典的key和value對調
mcase = {‘a‘: 10, ‘b‘: 34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)
3、 內置函數
見過的
‘‘‘
len()
print()
input()
range()
list()
tuple()
str()
int()
set()。。。。。
‘‘‘
dict()
field = ["id","name","age","phone","job"]
def yie_file():
with open("yuan_gong",encoding="utf-8") as f:
for line in f:
yield line.strip().split()
li = []
for i in yie_file():
dic = dict(zip(field,i))
if int(dic[‘age‘]) > 25:
print(dic)
else:
li.append(dic)
print(li)
結果:
{‘id‘: ‘4‘, ‘name‘: ‘houbinglei‘, ‘age‘: ‘27‘, ‘phone‘: ‘17718351482‘, ‘job‘: ‘IT‘}
[{‘id‘: ‘2‘, ‘name‘: ‘Egon‘, ‘age‘: ‘23‘, ‘phone‘: ‘13304320533‘, ‘job‘: ‘Tearcher‘}, {‘id‘: ‘3‘, ‘name‘: ‘nezha‘, ‘age‘: ‘25‘, ‘phone‘: ‘1333235322‘, ‘job‘: ‘IT‘}]
1.1. 作用域相關
locals :函數會以字典的類型返回當前位置的全部局部變量。
globals:函數以字典的類型返回全部全局變量。
1.2 其他相關
1.2.1 字符串類型代碼的執行,eval,exec
eval:去除字符串兩邊的引號,輸出裏邊的結果,並返回最終結果。執行字符串表達式。
print(eval(‘1 + 2 +3‘))
print(eval("{‘name‘:‘alex‘}"),type(eval("{‘name‘:‘alex‘}")))
exec:也是去除兩邊的引號,但是不返回結果,執行代碼,執行文件。
s1 = ‘‘‘
for i in range(5):
print(i)
‘‘‘
print(exec(s1))
1.2.2 輸入輸出相關
‘‘‘ 源碼分析
def print(self, *args, sep=‘ ‘, end=‘\n‘, file=None): # known special case of print
"""
print(value, ..., sep=‘ ‘, end=‘\n‘, file=sys.stdout, flush=False)
file: 默認是輸出到屏幕,如果設置為文件句柄,輸出到文件
sep: 打印多個值之間的分隔符,默認為空格
end: 每一次打印的結尾,默認為換行符
flush: 立即把內容輸出到流文件,不作緩存
"""
‘‘‘
print(111,222,333,sep=‘*‘) # 111*222*333
print(111,end=‘‘)
print(222) #兩行的結果 111222
f = open(‘log‘,‘w‘,encoding=‘utf-8‘)
print(‘寫入文件‘,file=f,flush=True)
1.2.3 內存相關
hash:獲取一個對象(可哈希對象:int,str,Bool,tuple)的哈希值。
id:用於獲取對象的內存地址。
print(hash(‘arg‘))
print(id(‘abc‘)) # 2033192957072
1.2.3文件操作相關
open:函數用於打開一個文件,創建一個 file 對象,相關的方法才可以調用它進行讀寫。
1.2.4模塊相關__import__
import:函數用於動態加載類和函數 。
1.2.5幫助
help:函數用於查看函數或模塊用途的詳細說明。
1.2.6 調用相關
callable:函數用於檢查一個對象是否是可調用的。如果返回True,object仍然可能調用失敗;但如果返回False,調用對象ojbect絕對不會成功。
name = ‘alex‘
def func1():
print(111)
print(callable(name)) False
print(callable(func1)) True
函數名加括號就能用,再面向對象比較有用。
1.2.7查看內置屬性
dir:函數不帶參數時,返回當前範圍內的變量、方法和定義的類型列表;帶參數時,返回參數的屬性、方法列表。
dir() # 獲得當前模塊的屬性列表
1.3 叠代器生成器相關
# 首先獲得Iterator對象:
it = iter([1, 2, 3, 4, 5])
# 循環:
while True:
try:
# 獲得下一個值:
x = next(it)
print(x)
except StopIteration:
# 遇到StopIteration就退出循環
break
iter:函數用來生成叠代器(講一個可叠代對象,生成叠代器)。
from collections import Iterable
from collections import Iterator
l = [1,2,3]
print(isinstance(l,Iterable)) # True
print(isinstance(l,Iterator)) # False
l1 = iter(l)
print(isinstance(l1,Iterable)) # True
print(isinstance(l1,Iterator)) # True
1.4 基礎數據類型相關
1.4.1數字相關(14)
數據類型(4):
bool :用於將給定參數轉換為布爾類型,如果沒有參數,返回 False。
int:函數用於將一個字符串或數字轉換為整型。
float:函數用於將整數和字符串轉換成浮點數。
進制轉換(3):
bin:將十進制轉換成二進制並返回。
oct:將十進制轉化成八進制字符串並返回。
hex:將十進制轉化成十六進制字符串並返回。
數學運算(7):
abs:函數返回數字的絕對值。
print(abs(-5)) # 5
divmod:計算除數與被除數的結果,返回一個包含商和余數的元組(a // b, a % b)。
print(divmod(7,2)) # (3, 1)
round:保留浮點數的小數位數,默認保留整數。
print(round(7/3,2)) # 2.33
print(round(7/3)) # 2
pow:求xy次冪。(三個參數為xy的結果對z取余)
print(pow(2,3)) # 兩個參數為2**3次冪
print(pow(2,3,3)) # 三個參數為2**3次冪,對3取余。
sum:對可叠代對象進行求和計算(可設置初始值)。
l1 = [i for i in range(100)]
print(sum(l1))
print(sum(l1,100)) # 初始值是100 ,最後算完再加上100
min:返回可叠代對象的最小值(可加key,key為函數名,通過函數的規則,返回最小值)。
print(min([1,2,3])) # 返回此序列最小值
ret = min([1,2,-5,],key=abs) # 按照絕對值的大小,返回此序列最小值
print(ret)
dic = {‘a‘:3,‘b‘:2,‘c‘:1}
print(min(dic,key=lambda x:dic[x]))
###這裏可叠代對象如果是字典,x默認是每個字典的key值;
###如果可叠代對象是s = [[3,2],[7,4],[1,6]]這種,x會默認接收每個元素的第一個值。
max:返回可叠代對象的最大值(可加key,key為函數名,通過函數的規則,返回最大值)
dic = {‘a‘:3,‘b‘:2,‘c‘:1}
print(max(dic,key=lambda x:dic[x]))
# x為dic的key,lambda的返回值(即dic的值進行比較)返回最大的值對應的鍵,x默認接收字典的key。
1.4.2和數據結構相關(24)
列表和元祖(2)
list:將一個可叠代對象轉化成列表(如果是字典,默認將key作為列表的元素)。
tuple:將一個可叠代對象轉化成元祖(如果是字典,默認將key作為元祖的元素)。
l = list((1,2,3))
print(l)
l = list({1,2,3})
print(l)
l = list({‘k1‘:1,‘k2‘:2})
print(l)
相關內置函數(2)
reversed:將一個序列翻轉,並返回此翻轉序列的叠代器。
l3 = [2, 3, 9, 8, 7, 4]
l3.reverse()
print(l3)
l_obj = reversed(l3)
print(l_obj) #<list_reverseiterator object at 0x0000025DDEB47908>
for i in l_obj:
print(i)
print(sum(l_obj)) # 33 sum直接求和叠代器。
print(sum(l3)) # 33 sum 本身就可以求和可叠代對象。
slice:構造一個切片對象,用於列表的切片。
字符串相關(9)
str:將數據轉化成字符串。
format:與具體數據相關,用於計算各種小數,精算等。
print(format(‘test‘, ‘<30‘)) 左對齊
print(format(‘test‘, ‘>20‘)) 右對齊
print(format(‘test‘, ‘^20‘)) 劇中
bytes:用於不同編碼之間的轉化。相當於encode
s1 = "abc"
print(bytes(s1,encoding="utf-8"))
print(s1.encode("utf-8"))
兩種方法將str轉換為bytes數據類型;解碼只能用decode
ord:輸入字符找該字符編碼的位置 unicode
print(ord(‘a‘)) # 97
print(ord(‘中‘)) #20013
chr:輸入位置數字找出其對應的字符
print(chr(97))
print(chr(20013))
ascii:是ascii碼中的返回該值,不是就返回/u...
print(ascii(‘a‘))
print(ascii(‘中‘))
repr:返回一個對象的string形式(原形畢露)。
print(repr(‘{"name":"alex"}‘),type(repr(‘{"name":"alex"}‘))) #‘{"name":"alex"}‘ <class ‘str‘>
print(‘{"name":"alex"}‘)
print(‘python%s期‘ % ‘22‘) # python22期
print(‘python%r期‘ % ‘22‘) # python‘22‘期
數據集合(3)
dict:創建一個字典。
set:創建一個集合。
frozenset:返回一個凍結的集合,凍結後集合不能再添加或刪除任何元素。
*** sorted:對所有可叠代的對象進行排序操作。返回列表。
L = [(‘a‘, 1), (‘c‘, 3), (‘d‘, 4),(‘b‘, 2), ]
sorted(L, key=lambda x:x[1]) # 利用key
[(‘a‘, 1), (‘b‘, 2), (‘c‘, 3), (‘d‘, 4)]
x:自動獲取可叠代對象的每一個值,並默認按照每個元素的第一個值排序。
字典默認是對Key排序。
dic = {"c":1,"a":3,"b":9}
print(sorted(dic)) #[‘a‘, ‘b‘, ‘c‘]
students = [(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
sorted(students, key=lambda s: s[2]) # 按年齡排序
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)]
sorted(students, key=lambda s: s[2], reverse=True) # 按降序
[(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
*** enumerate:枚舉,返回一個枚舉對象。
dic = {"c":1,"a":3,"b":9}
for i in enumerate(dic):
print(i)
結果:
(0, ‘c‘)
(1, ‘a‘)
(2, ‘b‘)
for index,key in enumerate(dic):
print("序號{}的值是{}".format(index,key))
結果:
序號0的值是c
序號1的值是a
序號2的值是b
all:可叠代對象中,全都是True才是True
any:可叠代對象中,有一個True 就是True
l1 = [1, ‘alex‘, 3]
l2 = [0, ‘‘, False,(), 1]
print(all(l1))
print(any(l2))
***zip 拉鏈方法,函數用於將可叠代的對象作為參數,將對象中對應的元素打包成一個個元組,並沒有返回列表,需要用for循環讀取這個叠代器。
l1 = [1,2,3,]
l2 = [‘a‘,‘b‘,‘c‘,5]
l3 = (‘*‘,‘**‘,(1,2,3),666,777)
for i in zip(l1, l2, l3):
print(i)
結果:
(1, ‘a‘, ‘*‘)
(2, ‘b‘, ‘**‘)
(3, ‘c‘, (1, 2, 3))
***map:會根據提供的函數對指定序列做映射。返回的是叠代器,類似於列表推導式的遍歷模式。
>>>def square(x) : # 計算平方數
... return x ** 2
...
>>> map(square, [1,2,3,4,5]) # 計算列表各個元素的平方
[1, 4, 9, 16, 25]
<map object at 0x00000268A1747908>
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函數
[1, 4, 9, 16, 25]
# 提供了兩個列表,對相同位置的列表數據進行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]
filter:過濾·。
類似於[i for i in range(1,8) if i % 2 == 0 ]
def func(x):return x%2 == 0
ret = filter(func,[1,2,3,4,5,6,7])
print(ret) #<filter object at 0x0000018EE48679B0>
for i in ret:
print(i)
portfolio = [
{‘name‘: ‘IBM‘, ‘shares‘: 100, ‘price‘: 91.1},
{‘name‘: ‘AAPL‘, ‘shares‘: 50, ‘price‘: 543.22},
{‘name‘: ‘FB‘, ‘shares‘: 200, ‘price‘: 21.09},
{‘name‘: ‘HPQ‘, ‘shares‘: 35, ‘price‘: 31.75},
{‘name‘: ‘YHOO‘, ‘shares‘: 45, ‘price‘: 16.35},
{‘name‘: ‘ACME‘, ‘shares‘: 75, ‘price‘: 115.65}]
ret = filter(lambda x:x[‘price‘] > 100, portfolio )
print(ret) # <filter object at 0x0000021B7F357E48>
for i in ret:
print(i)
min,max,sorted,map,filter
返回結果:
filter: ret = filter(lambda x:x[‘price‘] > 100, portfolio )
print(ret)
<filter object at 0x0000021B7F357E48> 返回叠代器
sorted: students = [(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
sorted(students, key=lambda s: s[2]) # 按年齡排序
[(‘dave‘, ‘B‘, 10), (‘jane‘, ‘B‘, 12), (‘john‘, ‘A‘, 15)] 返回列表
zip: ret = zip(l_new,l2,tu)
print(ret) <zip object at 0x00000292D35BE5C8> 返回叠代器
for i in a:
print(i)
(3, ‘oldboy‘, ‘**‘) 返回元祖
map: ret = map(lambda x:x[‘shares‘] * x[‘price‘], portfolio) # 字典的兩個值相乘。
print(ret) <map object at 0x000002CFC04E7EB8> 返回叠代器
li = []
for i in ret:
li.append(i)
print(li)
list: l=[{‘name‘:‘alex‘},{‘name‘:‘y‘}]
ret = map(lambda x:x[‘name‘]+‘SB‘, l) ret是叠代器。
print(list(ret)) list()將可叠代對象轉換為列表,同樣可以直接轉換叠代器。
結果: [‘alexSB‘, ‘ySB‘]
4 匿名函數
def func(x,y): return x + y
print(func(3,4))
func1 = lambda x,y: x + y
print(func1(3,4))
#def func1(x): return x**2
res = map(lambda x: x**2,[1,5,7,4,8])
for i in res:
print(i)
5.函數的有用信息
from functools import wraps
def logger(f):
@wraps(f)
def inner(*args, **kwargs):
"""
:param args: 函數名,密碼
:param kwargs: 備用
:return: True
"""
ret = f(*args, **kwargs)
return ret
return inner
@logger
def login(username,password):
"""
此函數是完成登錄功能的函數,需要用戶名,和密碼兩個參數,返回True 登陸成功
:return: True
"""
print(666)
return True
login(1,2) #inner()
# # login(‘alex‘, 123)
print(login.__doc__)
print(login.__name__)
遇到裝飾器的時候,要還是打印原函數的有用信息,需要from functools import wraps。並且正在inner函數上添加@wraps(f)。
6. 裝飾器的升級
帶參數的裝飾器
1,將@ 與函數分開@ timmerout(flag) 返回了timmer
2,將@timmer結合
def timmerout(flag1): # flag1 =flag
def timmer(f):
def inner(*args,**kwargs):
if flag1:
print(flag1)
start_time = time.time()
ret = f(*args,**kwargs)
end_time = time.time()
print(‘此函數的執行效率%s‘ % (end_time - start_time))
return ret
else:
ret = f(*args, **kwargs)
return ret
return inner
return timmer
@timmerout(‘京東‘) # 1,將@ 與函數分開@ timmerout(flag) 返回了timmer 2,將@timmer結合。
def JDshop():
time.sleep(0.3)
print(‘非常復雜......‘)
return 666
@timmerout(‘京東‘)
def JD():
time.sleep(0.3)
print(‘非常復雜......‘)
return 666
@timmerout(‘淘寶‘)
def taobao():
time.sleep(0.1)
print(‘非常復雜......‘)
return 666
@timmerout(‘淘寶‘)
def taobaoshop():
time.sleep(0.1)
print(‘非常復雜......‘)
return 666
taobaoshop()
結果 :
淘寶
非常復雜......
此函數的執行效率0.10024571418762207
多個裝飾器裝飾一個函數
@wrapper2 # f = warpper2(f) 裏面的f是inner1 外面的f是inner2
@wrapper1 # f = warpper1(f) 裏面的f函數名 外面的f 是inner1
def f():
print(‘in f‘) # 3
f() # inner2()
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
day05_雷神_函數進階