4 - 函數&裝飾器 and 叠代器&生成器
函數是什麽
函數一詞來源於數學,但編程中的「函數」概念,與數學中的函數是有很大不同的。程序裏函數的定義是:
定義:將一組語句的集合通過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名即可
特性:
- 減少重復代碼
- 使程序變的可擴展
- 使程序變得易維護
實例1
def calcu(x,y):
res = x**y
return res #返回執行結果
result = calc(2,2)
print(result )
實例2
def student_fun(name,age,post): print("----學生信息------") print("姓名:",name) print("年齡:",age) print("職業:",post) print(‘‘) student_fun(‘鄒俊安‘,17,‘學生‘) student_fun(age=17,name=‘文藝‘,post=‘學生‘) student_fun(‘王秋傑‘,45,‘老師‘)
函數的參數
形參:變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量
實參:可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值
name = "鄒俊安" def change_name(name): print("修改前:", name) name = "羅奧" print("修改後", name) change_name(name)print("name是什麽?", name) #輸出的name還是鄒俊安
函數的作用域
函數內一般情況無法修改函數外變量
name = "鄒君安" def change_name(): name = "羅奧" change_name(name) print("name是什麽?", name) #name還是鄒俊安
可以通過global關鍵字來訪問外部變量
name = "鄒君安" def change_name(): global name name = "羅奧" change_name(name) print("name是什麽?", name) #name還是鄒俊安
函數遞歸
在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
註意:
1. 必須有一個明確的結束條件。
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少。
3. 遞歸效率不高,遞歸層次過多會導致棧溢出。(經過測試python3.6的最大的遞歸此時為978次)
def calc(n): print(n) if int(n/2) ==0: return n return calc(int(n/2)) calc(10) """ 輸出: 10 5 2 1 """
匿名函數
匿名函數就是不需要顯式的指定函數
def calc1(n): return n ** 2 calc2 = lambda n: n ** 2 #結果相同 print(calc1(10)) print(calc2(10))
高階函數
一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。
def f(n): return n*2 def add(a,b,f): return f(a) + f(b) result = add(1,2,f) print(result) #結果:6
裝飾器
需要知識
1.函數即變量
2.高階函數
a.把函數名當實參傳給另外一個函數
b.返回值包含函數名
3.嵌套函數
高階函數+嵌套函數=》裝飾器
*裝飾器*
定義:本質是函數,(裝飾其他函數)就是為其他函數添加功能
原則:a.不能修改被裝飾的函數源代碼
b.不能修改被裝飾的函數調用方式
模型:
def 函數名1(裝飾器參數): def 函數名2(被裝飾函數名): def 函數名3(被裝飾函數的參數) 。。使用裝飾器參數。。 返回值 = 被裝飾函數使用(傳遞被裝飾函數的參數) 。。balabala。。 return 返回值 return 函數名3 return 函數名2 @函數名1(裝飾器參數) def 裝飾函數(參數): 。。balabala。。
現在你新入職了一家公司,工作是維護更新本公司網站,公司網站有3個入口: index、manage、topic,現在公司要求要在manage和topic入口需要登陸驗證,函數代碼極其復雜,而且很多地方都有調用,這時裝飾器就派上了用處。
實例:
username,password = ‘09w09‘,‘12345‘ def check_user(check_type): def decorator(func): def func_num(*arg1,**arg2): if check_type == True: usernm = input("Please input username:") passwd = input("Please input username:") if usernm == username and passwd == password: res = func(*arg1,**arg2) print(‘執行函數後繼續執行‘.center(50,‘-‘)) return res else: exit(0) else: passwd = input("09w09 please input password:") if passwd == password: res = func(*arg1, **arg2) print(‘執行函數後繼續執行‘.center(50, ‘-‘)) return res else: exit(0) return func_num return decorator def index(): print(‘Welcome to 09w09\‘s index‘.ljust(50,‘*‘)) @check_user(True) def manage(x): print(‘this is manage page!‘.ljust(50,‘*‘),x) @check_user(False) def topic(): print(‘this is topic page‘.ljust(50,‘*‘)) return ‘\nok!\n‘ index() manage(‘09w09‘) print(topic())
叠代器
叠代是Python最強大的功能之一,是訪問集合元素的一種方式。
叠代器是一個可以記住遍歷的位置的對象。
叠代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。叠代器只能往前不會後退。
叠代器僅僅在叠代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合,比如幾個G的文件
實例:
>>> a = iter([1,2,3,4,5]) >>> a <list_iterator object at 0x00000238F2D6DE48> >>> a.__next__() 1 >>> a.__next__() 2 >>> next(a) 3 >>> next(a) 4 >>> next(a) 5 >>> next(a) Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> next(a) StopIteration
生成器
在 Python 中,使用了 yield 的函數被稱為生成器(generator)。
跟普通函數不同的是,生成器是一個返回叠代器的函數,只能用於叠代操作,更簡單點理解生成器就是一個叠代器。
在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行
實例1:
#生成器變成list print([i*2 for i in range(10)]) #list變成生成器 print(iter([1,2,3,4,10,6,7,8]))
實例2:
def produce(x): str = ‘*‘ for i in range(x): yield str str+=‘*‘ def print_(p): while True: try: print(next(p)) except StopIteration : print(‘ok:‘) break print_(produce(10)) """ 輸出結果: * ** *** **** ***** ****** ******* ******** ********* ********** ok! """
yield實現在單線程的情況下實現並發運算的效果
import time def consumer(name): print(‘%s同學準備吃包子了‘ % name) while True: baozi = yield #每次執行都會停留在這裏, print("%s同學吃了%s餡包子" % (name,baozi)) def producer(filling): c1 = consumer(‘陳敏‘) c2 = consumer(‘馬國正‘) c1.__next__() c2.__next__() print(‘王嘉寧開始做包子了!‘) for i in range(10): time.sleep(1) print(‘陳敏做了2個%s餡包子‘ % filling) c1.send(filling) c2.send(filling) producer(‘韭菜‘)
4 - 函數&裝飾器 and 叠代器&生成器