#函數的嵌套調用:在調用一個函數的過程當中,又調用了其餘函數python
def max2(x,y)web
if x > y:閉包
return xapp
else:函數
return y
url
def max4(a,b,c,d):spa
res1=max2(a,b)code
res2=max2(res1,c)
對象
res3=max2(res2,d)blog
return res3
print(max4(1,2,3,-1))
#函數嵌套定義:在一個函數的內部又定義了一個另外的函數
def f1():
x=1
def f2():
print('from f2')
print(x,f2)
f1()
函數內部定義 在外部訪問不了,只能在內部訪問
問題:爲何在f1裏面定義了f2 只能在內部使用 就是下面的名稱空間的定義
2.名稱空間與做用域
#名稱空間:存放名字的地方,準確的說名稱空間是存放名字與變量值綁定關係的地方
python中名稱空間分爲三種
1 內置名稱空間 #print len max 存放python自帶的名字,那麼何時產生呢?顯而易見確定是python解析器啓動後產生
2 全局名稱空間 #在執行文件時產生存放文件級別定義名字,那麼什麼是文件級別的名字?沒有縮進基本都是
如下這些都屬於全局名稱空間
x=10
import os
def func():
pass
class Foo():
pass
if x==1:
z=3
3 局部名稱空間 #在執行文件的過程當中若是調用了函數則會產生該函數的局部名稱空間、
用來存放該函數內定義的名字,更名字在調用函數時生效,在函數調用結束後實效
那麼這三個名稱空間加載順序 :內置名稱空間->全局名稱空間->局部名稱空間
取值順序或者說名字的查找順序:局部名稱空間->全局名稱空間->內置名稱空間
例子:
max=1
def foo():
max=2
print(max)
foo() #依次註釋max 查看max值的變化
做用域:做用域即範圍
做用域分兩種
1 全局範圍:全局存活,全局有效 #在任何位置都能訪問globals()
2 局部範圍:臨時存活,局部有效 #只能在函數內部訪問locals()
def f1():
x=1
y=2
def f2():pass
print(locals())#查看局部
print(globals())#查看全局
print(locals() is globals()) 外部調用 局部就是全局結果爲true
print(dir(globals()))
#global nonlocal關鍵字
x=1
def f1():
x=2
def f2():
global x #在局部中不要儘可能不要改全局變量
nonlocal x #修改當前x的值爲上一層的值 注意nonlocal只能修改局部不能修改全局,全局用global
x=3
print(x) #x=2
f1()
print(x)
-------------
l=[]
def f2():
l.append('f2') #l是可變類型全部能夠修改 針對全局不可變類型須要加global
f2()
print(l)
#優先掌握:做用域關係,在函數定義時就已經固定了,
與調用位置無關
x=1
def f1():
def f2():
print(x)
return f2 #暫時不考慮遞歸
func=f1()
print(func)
3 閉包函數
大前提:做用域關係,在函數定義時就已經固定
,於調用位置無關,在調用函數時,必須必須必須
回到函數原來定義的位置去找做用域關係
#閉包函數:
#1. 定義在函數內部的函數
#2. 包含對外部做用域名字的引用,而不是對全局做用域名字的引用
#那麼該內部函數就稱爲閉包函數
x=1
def f1():
x=11111111111 #最後x結果
def f2():
print(x)
return f2
func=f1()
x=1000 #閉包函數 只會打印函數內部的值 外部不會改變
func()
那麼有什麼用的?
def deco():
x=11
def wrapper():
print(x)
return wrapper # 須要打破層級在外部用 因此須要return
func=deco() #這時deco()是固定參數 不須要傳參
func()
寫一個爬取網頁程序:閉包函數應用
import requests
def http_web(url):
#url='https://www.baidu.com'
def get():
return requests.get(url).text
return get
baidu_web=http_web('https://www.baidu.com')
python_web=http_web('https://www.python.org')
print(baidu_web())
print(python_web())
4 裝飾器--->閉包函數的一種應用場景
#1 開放封閉原則:對擴展是開放的 對修改是封閉的
#2 裝飾器:裝飾器的目的是爲其餘人添加新功能
#裝飾器自己能夠是任意可調用對象,被裝飾的對象自己也能夠是任意可調用對象
ps若是有多個裝飾器 也要按照前後順序
#2.1 裝飾器的遵循的原則 1 不修改被裝飾對象的源代碼 2 不修改被調用對象的調用方式
#2.2 裝飾器的目的是:在遵循1和2原則的前提 爲其餘新功能函數添加
#@裝飾器名,必須寫在被裝飾的對象的正上方,而且是單獨一行
例子:
import time
def timmer(func):
# func=index
def wrapper():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
return wrapper
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
@timmer # home=timmer(home)
def home():
time.sleep(2)
print('welcome to home page')
index()
home()
有參數裝飾器
import time
def timmer(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print('run time is %s' %(stop-start))
return res
return wrapper
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
return 123
@timmer # home=timmer(home)
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
# res=index() #res=wrapper()
# print(res)
res1=home('egon') #wrapper('egon')
print(res1)
5 迭代器
#迭代:是一個重複的過程,每一次重複,都是基於上一次的結果而來 # while True: #單純的重複 # print('你瞅啥') # l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) # count+=1 dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不適於沒有索引的數據類型 #迭代器: #可迭代對象iterable:凡是對象下有__iter__方法:對象.__iter__,該對象就是可迭代對象 # s='hello' # l=['a','b','c','d'] # t=('a','b','c','d') # dic={'name':'egon','sex':'m',"age":18} # set1={1,2,3} # f=open('db.txt') # s.__iter__() # l.__iter__() # t.__iter__() # dic.__iter__() # set1.__iter__() # f.__iter__() #迭代器對象:可迭代對象執行內置的__iter__方法,獲得的結果就是迭代器對象 # dic={'name':'egon','sex':'m',"age":18} # # i=dic.__iter__() # # print(i) #iterator迭代器 # # # i.__next__() #next(i) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration # # l=['a','b','c','d'] # # i=l.__iter__() # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration #不依賴於索引的取值方式 # l=['a','b','c','d'] # dic={'name':'egon','sex':'m',"age":18} # iter_l=iter(l) # iter_dic=iter(dic) # while True: # try: # # print(next(iter_l)) # k=next(iter_dic) # print(k,dic[k]) # except StopIteration: # break #什麼是迭代器對象: #1 有__iter__,執行獲得仍然是迭代自己 #2 有__next__ #迭代器對象的優勢 #1:提供了一種統一的(不依賴於索引的)迭代方式 #2:迭代器自己,比起其餘數據類型更省內存 # l=['a','b','c','d'] # i=iter(l) # dic={'a':1,'b':2} # x=dic.keys() # print(x) # i=x.__iter__() # # with open('a.txt') as f: # # print(next(f)) # # print(next(f)) # # print(next(f)) # f.read() #迭代器對象的缺點 #1:一次性,只能日後走,不能回退,不如索引取值靈活 #2:沒法預知何時取值結束,即沒法預知長度 # l=['a','b','c','d'] # i=iter(l) # print(next(i)) # print(next(i)) # print(next(i)) #for循環原理 # # l=['a','b','c','d'] # for item in l: #iter_l=l.__iter__() # print(item) # for item in {1,2,3,4}: # print(item) # with open('a.txt') as f: # # for line in f: #i=f.__iter__() # # print(line) # print(f is f.__iter__()) #補充:判斷可迭代對象與迭代器對象(瞭解) from collections import Iterable,Iterator s='hello' l=['a','b','c','d'] t=('a','b','c','d') dic={'name':'egon','sex':'m',"age":18} set1={1,2,3} f=open('a.txt') # print(isinstance(s,Iterable)) # print(isinstance(l,Iterable)) # print(isinstance(t,Iterable)) # print(isinstance(dic,Iterable)) # print(isinstance(set1,Iterable)) # print(isinstance(f,Iterable)) print(isinstance(s,Iterator)) print(isinstance(l,Iterator)) print(isinstance(t,Iterator)) print(isinstance(dic,Iterator)) print(isinstance(set1,Iterator)) print(isinstance(f,Iterator))
6 生成器
#生成器:在函數內部包含yield關鍵,那麼該函數執行的結果是生成器 #生成器就是迭代器 #yield的功能: # 1 把函數的結果作生迭代器(以一種優雅的方式封裝好__iter__,__next__) # 2 函數暫停與再繼續運行的狀態是由yield # def func(): # print('first') # yield 11111111 # print('second') # yield 2222222 # print('third') # yield 33333333 # print('fourth') # # # g=func() # print(g) # from collections import Iterator # print(isinstance(g,Iterator)) # print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) # for i in g: #i=iter(g) # print(i) # def func(n): # print('我開動啦') # while True: # yield n # n+=1 # # g=func(0) # # # print(next(g)) # # print(next(g)) # # print(next(g)) # for i in g: # print(i) # # for i in range(10000): # print(i) # def my_range(start,stop): # while True: # if start == stop: # raise StopIteration # yield start #2 # start+=1 #3 # # g=my_range(1,3) # # # print(next(g)) # print(next(g)) # print(next(g)) # # # for i in my_range(1,3): # print(i) #yield與return的比較? #相同:都有返回值的功能 #不一樣:return只能返回一次值,而yield能夠返回屢次值 # python3 tail.py -f access.log | grep 'error' import time def tail(filepath): with open(filepath, 'r') as f: f.seek(0, 2) while True: line = f.readline() if line: yield line else: time.sleep(0.2) def grep(pattern,lines): for line in lines: if pattern in line: print(line,end='') grep('error',tail('access.log'))
7 三元表達式,列表解析,生成器表達式
# def foo(x): # if x > 3: # return 'ok' # else: # return 'no' # # x=10 # res=x if x > 3 else 'no' # print(res) # def max2(x,y): # return x if x > y else y # print(max2(1,3)) # name='xxx' # print('SB' if name == 'you' else 'your')