# 函數 —— 2天 # 函數的定義和調用 # def 函數名(形參): #函數體 #return 返回值 #被調用的地方接收 #調用 函數名(實參) # 站在形參的角度上 : 位置參數,*args,默認參數(陷阱),**kwargs # 站在實參的角度上 : 按照位置傳,按照關鍵字傳 # 返回值:沒有返回值 返回一個值 返回多個值 # 接收返回值:沒有返回值不接收,返回一個值用一個變量接收,返回多個值用一個變量或者對應數目的變量接收 # 閉包函數 —— 在內部函數引用外部函數的變量 # 裝飾器函數—— 裝飾器必定是閉包函數 # 裝飾器的做用 : 在不改變原來函數的調用方式的狀況下 在這個函數的先後添加新的功能 # 完美的符合了一個開發原則 :開放封閉原則 # 對擴展是開發的 # 對修改是封閉的 # 基礎的裝飾器 # from functools import wraps # def wrapper(func): # @wraps(func) # def inner(*args,**kwargs): # '''在函數被調用以前添加的代碼''' # ret = func(*args,**kwargs) # func是被裝飾的函數 在這裏被調用 # '''在函數被調用以後添加的代碼''' # return ret # return inner # 使用 —— @wrapper # @wrapper # def func(): #inner # pass # # func.__name__ # 帶參數的裝飾器 # @wrapper -- > @warapper(argument) # 三層嵌套函數 # def outer(形參): # def wrapper(func): # def inner(*args,**kwargs): # '''在函數被調用以前添加的代碼''' # ret = func(*args,**kwargs) # func是被裝飾的函數 在這裏被調用 # '''在函數被調用以後添加的代碼''' # return ret # return inner # return wrapper # @outer(True) # def func(): # pass # 多個裝飾器裝飾一個函數 # 俄羅斯套娃 #def wrapper1(func): # @wraps(func) # def inner(*args,**kwargs): # print('before 1') # print('******') # ret = func(*args,**kwargs) # func是被裝飾的函數 在這裏被調用 # '''在函數被調用以後添加的代碼''' # return ret # def wrapper2(func): # @wraps(func) # def inner(*args,**kwargs): # print('before 2') # ret = func(*args,**kwargs) # func是被裝飾的函數 在這裏被調用 # '''在函數被調用以後添加的代碼''' # return ret # @wrapper1 # @wrapper2 # def func(): # print('111') # 迭代器和生成器 —— 兩天 # 內置函數 —— 兩天
#雙下方法 print([1].__add__([2])) print([1]+[2]) <<< [1, 2] [1, 2]
#list dic str set tuple range enumerate print(dir([])) #告訴我列表的全部方法 ret=set(dir([]))&set(dir({}))&set(dir(""))&set(dir(range(12))) print(ret) print(set(dir([]))-set(dir({}))) <<< ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] {'__gt__', '__reduce_ex__', '__doc__', '__getitem__', '__len__', '__sizeof__', '__new__', '__eq__', '__delattr__', '__str__', '__reduce__', '__format__', '__repr__', '__ne__', '__le__', '__lt__', '__iter__', '__getattribute__', '__init__', '__contains__', '__subclasshook__', '__setattr__', '__dir__', '__class__', '__ge__', '__init_subclass__', '__hash__'} {'__iadd__', '__imul__', '__mul__', 'count', 'index', 'sort', 'reverse', 'append', '__rmul__', 'extend', 'remove', 'insert', '__reversed__', '__add__'}
''' 可迭代協議: 只要能被for循環的數據類型 就必定有__iter__方法 [] iterable 只要含有__iter__方法的都是可迭代的 迭代器協議: 一個列表執行了__iter__()以後的返回值就是一個迭代器 [].__iter__ iteraor 內部含有__iter__和__next__方法的就是迭代器 經過__next__()就能夠從迭代器中一個一個取值 :print(iterator.__next__()) for: for循環其實就是在使用迭代器 只有是可迭代對象的時候才能用for 當咱們用一個新的變量 不肯定能不能for循環的時候 就判斷是否可迭代 判斷方法 from _collections_abc import Iterable print(isinstance([],Iterable)) print('__iter__'in dir([])) '''
#協議 print([].__iter__()) #打印迭代器直接給你內存地址 print(set(dir([].__iter__()))-set(dir([]))) #列表迭代器至關於列表的獨特方法 print([1,'a','bbb'].__iter__().__length_hint__()) #__length_hint__求元素個數 l=[1,2,3] iterator=l.__iter__() print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) <<< <list_iterator object at 0x0000026048DF4438> {'__setstate__', '__next__', '__length_hint__'} 3 1 2 3
#判斷方法 print('__iter__'in dir([])) print('__iter__'in dir([].__iter__())) from _collections_abc import Iterable #棄用警告:不推薦使用或導入來自collections from collections.abc import Iterator #而不是「collections.abc」中的ABC print(isinstance([],Iterator)) # 而且在python3.8中它將中止工做 print(isinstance([],Iterable)) #判斷[]是否是可迭代的 <<< True True False True
#for #只要有iter方法就能被循環 for循環其實就是在使用迭代器 l=[1,2,3] for i in l.__iter__(): print(i) print([].__iter__()) #打印迭代器直接給你內存地址 print(range(10).__iter__()) print(range(10)) l=[1,2,3] for i in l: print(i) if i ==2: break <<< 1 2 3 <list_iterator object at 0x0000024B1E314208> <range_iterator object at 0x0000024B1DFAD830> range(0, 10) 1 2
# 迭代器的好處 ''' 從容器類型中一個個取值 會把全部值都取到 節省內存空間 迭代器並不會在內存中佔一大塊內存 而是隨着循環 每次生成一個next給我一個''' l=[1,2,3,4] iterator=l.__iter__() while 1: print(iterator.__next__()) <<< Traceback (most recent call last): File "C:/python全棧/me第一部分/day13 迭代器和生成器.py", line 76, in <module> print(iterator.__next__()) StopIteration 1 2 3 4
print(range(10000)) print(list(range(3))) def f(): for i in range(200): i="wahaha%s"%i return i print(f()) <<< range(0, 10000) [0, 1, 2] wahaha199
#3 生成器 #生成器函數 本質上就是咱們本身寫的函數 #只要含有yield關鍵字的函數都是生成器函數 #yield不能和return共用且須要寫在函數內 def generetor(): print(1) yield 'a' ret=generetor() print(ret) print(ret.__next__()) <<< <generator object generetor at 0x00000246FE4C8A98> 1 a
#生成器函數 執行以後會獲得一個生成器做爲一個返回值 def generetor1(): print(1) yield 'a' print(2) yield 'b' yield 'c' g=generetor1() print(g) ret=g.__next__() print(ret) # for i in g: # print(i) 1 a 2 b c ret=g.__next__() print(ret) ret = g.__next__() print(ret) <<< 1 a 2 b c
# 娃哈哈 import time def wahaha(): for i in range(200000): yield '娃哈哈%s'% i g=wahaha() g1=wahaha() print(g.__next__()) print(g.__next__()) print(g1.__next__()) g=wahaha() count=0 a=time.time() for i in g: count+=1 print(i) if count>3: break b=time.time() print(b-a) print("***",g.__next__()) for i in g: count+=1 print(i) if count>6: break print("&&",g.__next__()) <<< 娃哈哈0 娃哈哈1 娃哈哈0 娃哈哈0 娃哈哈1 娃哈哈2 娃哈哈3 0.0 *** 娃哈哈4 娃哈哈5 娃哈哈6 娃哈哈7 && 娃哈哈8
#4 利用生成器監聽文件輸入 def tail(filename): f=open(filename,encoding='utf-8') while True: line=f.readline() if line.strip(): yield line.strip() #使用生成器在後面的操做中更靈活想加*就加 g=tail('file') # print(g.__next__()) for i in g: if 'python' in i: print("***",i) <<< *** python