裝飾器、迭代器、生成器以及內置函數python
裝飾器:程序員
原函數先後增長功能,切不改變函數的本來使用方式app
import time
def wrapper(f):
def inner():
start = time.time()
f()
end = time.time()
print('執行效率爲%s'%(end-start))
return inner
@wrapper
def func():
print('this is func')
time.sleep(0.3)
func()ide
import time
def wrapper(f):
def inner(*args,**kwargs):#帶參數的裝飾器
start = time.time()
f(*args,**kwargs)
end = time.time()
print('執行效率爲%s'%(end-start))
return inner
@wrapper
def func(a,b):
print(a,b)
print('this is func')
time.sleep(0.3)
func(111,222)函數
再加一個666this
import time
def wrapper(f):
def inner(*args,**kwargs):#帶參數的裝飾器
start = time.time()
set = f(*args,**kwargs)
end = time.time()
print('執行效率爲%s'%(end-start))
return set
return inner
@wrapper
def func(a,b):
print(a,b)
print('this is func')
time.sleep(0.3)
return 666
print(func(111,222))spa
進階需求:設計
狀況一:3d
500個函數日誌
設計裝飾器,確認是否生效
import time
FLAG = True
def outer(flag):
def wrapper(f):
def inner(*args,**kwargs):#帶參數的裝飾器
if flag == True:
start = time.time()
set = f(*args,**kwargs)
end = time.time()
print('執行效率爲%s'%(end-start))
else:
set = f(*args,**kwargs)
return set
return inner
return wrapper
@outer(FLAG)
def func(a,b):
print(a,b)
print('this is func')
time.sleep(0.3)
return 666
print(func(111,222))
狀況二:
登錄,紀錄日誌
login_info = {'alex':False}
def login(func):
def inner(name):
if login_info[name] !=True:
user = input('>>>user')
pwd = input('>>pwd')
if user =='alex' and pwd =='alex3714':
login_info[name] = True
if login_info[name] == True:
ret = func(name)
return ret
return inner
def wrapper1(func): #f
def inner1():
print('wrapper1 ,before func')
func() # f
print('wrapper1 ,after func')
return inner1
def wrapper2(func): # inner1
def inner2():
print('wrapper2 ,before func')
func() # inner1
print('wrapper2 ,after func')
return inner2
@wrapper2
@wrapper1
def f():
print('in f')
f()
import time
login_info = {'alex':False}
def login(func):
def inner(name):
if login_info[name] !=True:
user = input('>>>user')
pwd = input('>>pwd')
if user =='alex' and pwd =='alex3714':
login_info[name] = True
if login_info[name] == True:
ret = func(name)
return ret
return inner
def timmer(f):
def inner(*args,**kwargs):
start = time.time()
ret = f(*args,**kwargs)
end = time.time()
print('執行效率%s'%(end-start))
return ret
return inner
@login
@timmer
def index(name):
print('歡迎%s考到博客園'%name)
time.sleep(0.3)
@login
@timmer
def manager(name):
print('歡迎%s考到博客園管理頁面'%name)
time.sleep(0.3)
index('alex')
manager('alex')
迭代器和生成器
迭代器:
凡是可使用for循環取值的都是可迭代的
#從列表、字典中取值
# index索引
#for 凡是經過for循環取值的都是可迭代的
可迭代協議:
內部有__iter__方法的都是可迭代的
迭代器協議:
內部有__iter__和__next__方法的都是迭代器
建立迭代器使用__iter__() 或者 iter()
dir()能夠查看使用的內置方法
l = [1,2,3]
ll = iter(l)
print(ll.__next__())
print(ll.__next__())
l = [1,2,3]
lst_iter = iter(l) #lst_iter = iter(l) == lst_iter = [1,2,3].__iter__()
while True:
print(next(lst_iter)) #lst_iter.__next__()
l = [1,2,3]
ll = iter(l)
while True:
print(next(ll)) #報錯了
沒有就會出錯
l = [1,2,3]
lst_iter = iter(l) #lst_iter = iter(l) == lst_iter = [1,2,3].__iter__()
while True:
try:
print(next(lst_iter)) #lst_iter.__next__()
except StopIteration:
break
總結:
什麼是可迭代:內部有__iter__
什麼是迭代器:迭代器=iter(可迭代的) 自帶__next__方法
節省內存
Range()
from collections import Iterable,Iterator
print(range(10000))
print(isinstance(range(10000),Iterable)) #True
print(isinstance(repr(10000),Iterator)) #False
Python2的range會生成一個列表,將用來存儲生成全部的值
Python3,range無論要多少,都不會生成實際的值
在使用的時候在生成
for i in range(1000):
節省內存,速度快
特性:惰性運算
生成器:
本身寫的迭代器就是生成器
兩種本身寫生成器的機制:
生成器函數:
凡是帶有yield的函數是個生成器
def func():
print('****')
yield 1
g = func()
next(g)
def func():
print('****')
yield 1
print('^^^^')
yield 2
g = func()
print('___',next(g))
print('===',next(g))
Yield 記錄當前所在位置,等待下一次next來觸發函數的狀態
想要執行要next
def cloth_g(name):
for i in range(name):
yield 'choth_g%s'%i
g = cloth_g(10)
next(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
使用生成器監聽文件輸入:
import time
def lister_file():
with open('userinfo') as f1:
while True:
line = f1.readline()
if line.strip():
yield line.strip()
time.sleep(0.3)
g = lister_file()
for i in g:
print(i)
if i =='error':
break
Send 關鍵字
在執行next的時候,傳遞一個參數給生成器函數的內部
1)
def func():
print(1111)
yield 1
print(2222)
yield 2
print(3333)
yield 3
func()
next(func())
next(func())
2) :
def func():
print(1111)
yield 1
print(2222)
yield 2
print(3333)
yield 3
g = func()
ret = next(g)
print(ret)
3) :
def func():
print(1111)
ret1 = yield 1
print(2222,'ret1:',ret1)
ret2 = yield 2
print(3333,'ret2:',ret2)
yield 3
g = func()
ret = next(g)
print(g.send('alex'))
print(g.send('lxf'))
向生成器中傳遞值,有個激活過程,第一次必須用next觸發這個生成器
def average():
sum_money = 0 #總錢數
day = 0 #天數
avg = 0 #平均的錢
while True:
money = yield avg
sum_money += money
day +=1
avg = sum_money/day
g = average()
next(g)
print(g.send(200))
print(g.send(300))
例子:
預激生成器:
就是吧要激活的next放到一個裝飾器當中,好比說有多個程序須要激活的話,能夠這樣作,爲了簡便,若是要是就一個程序的話就沒有必要了
yield from:
def generator_func():
for i in range(5):
yield i
for j in 'hello':
yield j
g = generator_func()
#如何取值
#1,next、隨時能夠中止,最後會報錯
print(next(g))
print(next(g))
#2,for循環、從頭至尾遍歷一次,不遇到break、return不中止
for i in g:
print(i)
#3,list、tuple
print(list(g))#一次性全部的都轉換了,若是多太佔內存
print(g)
上面的內容能夠進行替換成以下:
def generator_func():
yield from range(5)
yield from 'hello'
# for i in range(5):
# yield i
# for j in 'hello':
# yield j
g = generator_func()
for i in g:
print(i)
總結:
1)生辰器函數,是咱們python程序員實現迭代器的一種手段
2)主要特徵是在函數中含有yield
3)調用一個生成器函數,不會執行這個函數中的代碼,只是會得到一個生成器代碼
4)只有從生辰器中取值的時候,纔會執行函數內部的代碼,且每獲取一個數據才執行的到這個數據的代碼
5)獲取數據方式,next、send 循環 數據類型的強制轉化
6)Yield 返回值的簡便方法,若是自己就是循環一個可迭代,且要把可迭代數據中的每個元素都返回,能夠用yield from
7)使用send的時候,在生成器創造出來以後須要進行預激活,這一步可使用裝飾器完成
8)生成器特色:節省內存、惰性運算
9)生成器用來解決內存和程序功能之間的解耦
列表推到試:表現爲 []
new = []
for i in range(10):
new.append(i**2)
print(new)
#上面的複雜很差
print([i **2 for i in range(10)])#列表推到式
ll = [1,2,3,-5,6,20,-7]#求每一個數的餘數
print([ i%2 for i in ll])
ll = [1,2,3,-5,6,20,-7]
print([i for i in ll if i %2 ==0])
#30之內搜友能被3整除的數
print([i for i in range(30) if i % 3 ==0])
#30之內搜友能被3整除的數的平方
print([i**2 for i in range(30) if i % 3 ==0])
#:找到嵌套列表中名字含有兩個‘e’的全部名字
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
# for i in names:
# for j in i: #複雜很差
# if j.count('e') ==2:
# print(j)
print( [j for i in names for j in i if j.count('e') ==2])
生成器表達式:表現爲 ()
練習題:
自定義函數:
本身定義的【name = ‘uuu’】
內置函數:
拿過來直接用的,python直接封裝好的
Print、len、max、min、dir
迭代器/生成器相關的:
Range、next 、iter
做用域相關的:
Globals
Locals
其餘:
Input:
Print:九九乘法表
for i in range(1,10):
for j in range(1,i+1):
print('%s*%s=%2s'%(i,j,i*j),end=' ')
print()
print(1,2,3,4,5,sep=';',end=' ')#1;2;3;4;5
print(1,2,3,4,5,sep=';',end='')#1;2;3;4;5
進度條
import time
for i in range(0,101,2):
time.sleep(0.1)
char_num = i//2
per_str = '\r%s%% : %s\n' % (i, '*' * char_num) if i ==100 else'\r%s%% : %s'%(i,'*'*char_num)
print(per_str,end='')
import time
for i in range(0,101,2):
time.sleep(0.1)
char_num = i//2
if i ==100:
per_str = '\r%s%% : %s\n' %(i,'*'* char_num)
else:
per_str='\r%s%%: %s'%(i,'*' *char_num)
print(per_str,end='')
Hash:
對可hash的數據類型進行hash以後會的到一個數字
在一次程序的執行過程當中,對相同的可哈希變量,哈希以後的結果永遠相同
在一次程序的執行過程當中,對不相同的可哈希變量,哈希以後的結果幾乎是不相同的
hash字典底層的存儲和set 集合的去重機制都有關
Id():
Open:
Import:
Help:
Callable:可調用
def func():
pass
a = 1
print(callable(func))#True
print(callable(a))#False
Dir: 查看這一個變量的全部方法、屬性
Bin:進制
:
print(bin(10))#二進制
print(oct(10))#十進制
print(hex(10))#十六進制
abs計算數字絕對值
print(abs(4))
print(abs(-4))
divmod:商餘函數
print(divmod(10,2))#(5, 0)
print(divmod(7,3))#(2, 1)
print(divmod(9,7))#(1, 2)
Round:小數精確
print(round(3.1415926,4))#3.1416 小數精確四捨五入
Pow:平方
print(pow(2,3))#8
print(pow(3,2))#9
Sum:求和
print(sum([1,2,3,4,5]))
Min:計算最小值
print(min([1,2,3,4,5]))#1
print(min([1,2,3,4,5]))#1
print(min(1,-2,3,-4,key=abs))#1
def func(num):
return num%2
print(min(-2,3,-4,key=func))
Max:和min同樣
List
Tuper
Reverse:反轉
Reversed()
ret = [1,2,3,4,5]
ret1 = reversed(ret)
ret2 = reversed((1,2,3,4,5))
print(ret)#[1, 2, 3, 4, 5]
print(list(ret1))#[5, 4, 3, 2, 1]
print(list(ret2))#[5, 4, 3, 2, 1]
Str
Format
Bytes
Ord
print(ord('a'))#小寫的a-z 97+26 大寫的A-Z 65+26
Chr
print(chr(97))#a
Repr:
print(repr(1))#1
print(repr('1'))#'1'
Enumerate:枚舉函數
l = ['蘋果','香蕉','橘子']
for index,i in enumerate(l,1):
print(index,i)
l = ['蘋果','香蕉','橘子']
ret = enumerate(l,1)
for i in ret:
print(i[0],i[1])
沒啥用:
Zip:拉鍊方法:
ss =zip([1,2,3,4],('a','b','c','d'))
for i in ss:
print(i)
Filter:用於過濾不須要的元素
ll = [1,4,6,7,12,17]
def func(num):
if num %2 ==0:return True
for i in filter(func,ll):
print(i)
g=(i for i in ll if i%2 ==0)
l = ['test',None,'','str', ' ','END']
def func(item):
if item and item.strip():return True
for i in filter(func,l):
print(i)
Map:
def func(num):
return num**2
for i in map(func,range(10)):print(i)
Sorted:排序功能
l = [1,-4,-2,3,-5,6,5]
l.sort(key=abs)
print(l)
l = [1,-4,-2,3,-5,6,5]
new = sorted(l,reverse=True)
print(new)
l = [[1,2,],[3,4,5,6],(7,),'123']
print(sorted(l,key=len))
eval:
eval('print(123)')
exec:
exec ('print(123)')#123
eval('print(123)')#123
print(eval('1+2-3*20/(2+3)')) -9.0
print(exec('1+2-3*20/(2+3)'))# none
匿名函數:
Lambda表達式:
邏輯比較簡單
1):
add = lambda a,b: a+b
print(add(1,2))
2):
def func(num):
return num**2
for i in map(func,range(10)):print(i)
for i in map(lambda num : num**2,range(10)):print(i)
3):
def func(num):
return num%2
print(max(-2,3,-4,key=func))
print(max(-2,3,-4,key=lambda num:num%2))
遞歸:
遞歸本身調用本身
須要有一箇中止的條件
二分法:
l = [1,2,3,4,5,6,7,8,9,10,11]
def binary_search(l,num):
print(l)
if len(l) == 0:
print('not has num')
return
mid_index = len(l)//2
if num > l[mid_index]:
binary_search(l[mid_index+1:],num)
elif num < l[mid_index]:
binary_search(l[0:mid_index],num)
else:
print('find it')
binary_search(l,9)