日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

第四篇: python函数续

發布時間:2025/3/14 python 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第四篇: python函数续 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、函數的嵌套

函數的嵌套調用:在調用一個函數的過程中,又調用了其它函數

示例1:

def bar():print('from nbar')def foo():print('from foo')bar() foo() #執行結果為 C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函數嵌套.py from foo from nbar

?

示例2:求函數所帶四個參數的最大值

def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):res1=max2(a,b)res2=max2(res1,c)res3=max2(res2,d)return res3 print(max(1,2,3,-1))#執行結果如下 C:\Users\Administrator\AppData\Local\Programs\Python\Python36\python.exe C:/Users/Administrator/PycharmProjects/python18/day4/函數嵌套.py 3

?

函數的嵌套定義:在一個函數的內部,又定義另外一個函數

2、名稱空間和作用域

名稱空間:存放名字的地方,準確的說名稱空間是存放名字與變量值綁定關系的地方
名稱空間共有三種名稱空間既:
  1、內置名稱空間:在python解釋器啟動時產生,存放一些python內置的名字
  2、全局名稱空間:在執行文件時產生,存放文件級別定義的名字
  3、局部名稱空間:在執行文件的過程中,如果調用了函數,則會產生該函數的局部名稱空間,用來存放該函數內定義的名字,該名字在函數調用時生效,在函數調用結束后失效

加載順序:內置===》全局===》局部


優先掌握一:名字的查找順序是:局部==》全局===》內置


作用域:作用的范圍
全局作用域:全局存貨,全局有效:globals()


局部作用域:臨時存活,局部生效:locals() x=11111111111111111111111111111111111111111111# def f1(): # x=1 # y=2 # def f2():pass # # print(locals()) # print(globals()) # # f1() # print(locals() is globals()) # print(locals()) # # print(dir(globals()['__builtins__']))#global nonlocal掌握 # x=1 # def f1(): # global x # x=2 # # f1() # print(x)# l=[] # def f2(): # l.append('f2') # # f2() # print(l)# x=0 # def f1(): # # x=1 # def f2(): # # x=2 # def f3(): # # global x # nonlocal x # x=3 # f3() # # print(x) # f2() # print(x) # f1() # print(x)

 

優先掌握二:作用域關系,在函數定義時就已經固定,于調用位置無關,在調用函數時,必須必須必須回到函數原來定義的位置去找作用域關系

x=1 def f1():def f2():print(x)return f2# func=f1() # print(func) # x=10000000 # func() # x=10000000def foo(func):x=300000000func() #f2() x=10000000000000000000000foo(f1()) # x=10000000000000000000000 # foo(f1())

  

3、閉包函數

1. 定義在函數內部的函數
2. 包含對外部作用域名字的引用,而不是對全局作用域名字的引用,那么該內部函數就稱為閉包函數

# x=1 # def f1(): # x=11111111111 # def f2(): # print(x) # return f2 # # func=f1()# x=1000 # func()# def foo(): # x=12312312312312312312312312312312312313123 # func() # # # foo()# def deco(): # x=123123123123 # def wrapper(): # print(x) # return wrapper # # func=deco()# func()

?

閉包函數的應用:惰性計算

import requests #pip3 install requests# def get(url): # return requests.get(url).text # # print(get('https://www.python.org')) # print(get('https://www.python.org')) # print(get('https://www.python.org')) # print(get('https://www.python.org'))# def index(url): # # url='https://www.python.org' # def get(): # # return requests.get(url).text # print(requests.get(url).text) # # return get # # python_web=index('https://www.python.org') # baidu_web=index('https://www.baidu.com')# python_web() # baidu_web()name='egon' def index(url):x=1y=2def wrapper():# x# y# return requests.get(url).textprint(name)return wrapperpython_web=index('https://www.python.org')# print(python_web.__closure__[0].cell_contents) print(python_web.__closure__) # print(python_web.__closure__[0].cell_contents) # print(python_web.__closure__[1].cell_contents) # print(python_web.__closure__[2].cell_contents)

?

4、裝飾器 

1、 開放封閉原則:對擴展是開放的,對修改是封閉

2、 裝飾器:裝飾它人的工具,裝飾器本身可以是任意可調用對象,被裝飾的對象本身也可以是任意可調用對象
  2.1 裝飾器的遵循的原則:

    2.1.1、 不修改被裝飾對象的源代碼

    2.1.2、 不修改被調用對象的調用方式

裝飾器名,必須寫在被裝飾對象的正上方,并且是單獨一行

import timedef timmer(func):# func=indexdef 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()  

裝飾器補充

#補充一:wraps# import time # from functools import wraps # # def timmer(func): # @wraps(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(): # '''這是index函數''' # time.sleep(3) # print('welcome to index') # return 123 # # print(index.__doc__) # # print(help(index))
#補充二:一個函數頭頂上可以多個裝飾器 import time from functools import wraps current_user={'user':None}def timmer(func):@wraps(func)def wrapper(*args,**kwargs):start=time.time()res=func(*args,**kwargs)stop=time.time()print('run time is %s' %(stop-start))return resreturn wrapper def auth(auth_type='file'):def deco(func):def wrapper(*args, **kwargs):if auth_type == 'file':if current_user['user']:return func(*args, **kwargs)name = input('name: ').strip()password = input('password: ').strip()with open('db.txt', encoding='utf-8') as f:user_dic = eval(f.read())if name in user_dic and password == user_dic[name]:res = func(*args, **kwargs)current_user['user'] = namereturn reselse:print('user or password error')elif auth_type == 'mysql':print('mysql')elif auth_type == 'ldap':print('ldap')else:print('not valid auth_type')return wrapperreturn deco@timmer #index=timmer(wrapper) @auth() # @deco #index=deco(index) #wrapper def index():'''這是index函數'''time.sleep(3)print('welcome to index')return 123# print(index.__doc__) # print(help(index))index()

  

5、生成器

?學習生成器之前,我們先來看看什么是列表生成式

#列表生成式 b = [ i*2 for i in range(10)] print(b)###########打印輸出########### #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

通過列表生成式,我們可以直接創建一個列表。但是,受到內存限制,列表容量肯定是有限的。而且,創建一個包含100萬個元素的列表,不僅占用很大的存儲空間,還需要花費很長時間,如果我們僅僅需要訪問前面幾個元素,那后面絕大多數元素占用的空間都白白浪費了。所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種調用時才會生成相應數據的機制,稱為生成器:generator

要創建一個generator,有很多種方法,第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個生成器

#生成器 l = [ i*2 for i in range(10)] print(l)g = (i*2 for i in range(10)) print(g)###########打印輸出########### #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] #<generator object <genexpr> at 0x0064AAE0>

print(g) 打印出來的信息顯示g是一個生成器,創建l和g的區別僅在于最外層的[]和(),l是一個list,而g是一個generator;我們可以直接打印出list的每一個元素,但我們怎么打印出generator的每一個元素呢?如果要一個一個打印出來,可以通過next()函數獲得generator的下一個返回值

#生成器next打印 print(next(g)) #......... 不斷next 打印10次 #.......... print(next(g))###########打印輸出########### #0 #........ #18 #Traceback (most recent call last): # File "<stdin>", line 1, in <module> #StopIteration

我們講過,generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的錯誤。

上面這種不斷調用next(g)實在是太變態了,正確的方法是使用for循環,因為generator也是可迭代對象,所以,我們創建了一個generator后,基本上永遠不會調用next(),而是通過for循環來迭代它,并且不需要關心StopIteration的錯誤

#生成器for調用 g = (i*2 for i in range(10)) #不用擔心出現StopIteration錯誤 for i in g:print(i)###########打印輸出########### # 0 # 2 # 4 # 6 # 8 # 10 # 12 # 14 # 16 # 18

generator非常強大。如果推算的算法比較復雜,用列表生成式轉換的生成器無法去實現時,我們還可以用函數來實現。比如,著名的斐波拉契數列(Fibonacci)  

#函數表示斐波拉契數列 def fib(max):n, a, b = 0, 0, 1while n < max:print(b)a, b = b, a + bn += 1return 'done'fib(5) ###########打印輸出########### # 1 # 1 # 2 # 3 # 5

仔細觀察,可以看出,fib函數實際上是定義了斐波那契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似generator;也就是說,上面的函數和generator僅一步之遙,那我們能不能把上面的函數變成一個生成器呢?  

#斐波拉契數列轉換為generator def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'print(type(fib(5))) #打印fib(5)的類型 for i in fib(5): #for循環去調用print(i) ###########打印輸出########### # <class 'generator'> # 1 # 1 # 2 # 3 # 5

要把fib函數變成generator,只需要把print(b)改為yield b就可以了,這就是定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,而是一個generator

但是用for循環調用generator時,會發現拿不到generator的return語句的返回值,也就是return的值沒有打印出來,現在我們來看看怎么去打印generator的返回值

#獲取generator的返回值 def fib(max):n, a, b = 0, 0, 1while n < max:#print(b)yield ba, b = b, a + bn += 1return 'done'g = fib(5) while True:try:x = next(g)print( x)except StopIteration as e:print(e.value)break ###########打印輸出########### # 1 # 1 # 2 # 3 # 5 # done

如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中,關于如何捕獲錯誤,后面的錯誤處理還會詳細講解。 

還可通過yield實現在單線程的情況下實現并發運算的效果

import time def consumer(name):print("%s 準備吃包子啦!" %name)while True:baozi = yieldprint("包子[%s]來了,被[%s]吃了!" %(baozi,name))def producer(name):c = consumer('A')c2 = consumer('B')c.__next__()        #c.__next__()等同于next(c)c2.__next__()print("老子開始準備做包子啦!")for i in range(10):time.sleep(1)print("%s做了2個包子!"%(name))c.send(i)c2.send(i)producer("lzl")

  

6、迭代器  

迭代:是一個重復的過程,每一次重復,都是基于上一次的結果而來  

# while True: #單純的重復 # print('你瞅啥')# l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) # count+=1dic={'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))

?

轉載于:https://www.cnblogs.com/junxun/p/7224615.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的第四篇: python函数续的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。