第四篇 函数
一.函數的定義
# 函數的定義def 函數名(形參):'''文檔字符串函數功能:函數參數:函數返回值'''function_bodyreturn [expression]# 函數的使用 函數名(實參) # 1. 函數的定義 def sayHello(name):print("你好,{},很高興再次見到你".format(name))return "{}來北京看我了".format(name)#函數的調用 print(sayHello("dali"))# 輸出 你好,dali,很高興再次見到你 dali來北京看我了?
# 2. 函數可以沒有參數 def Hello():a= 3+4return aprint(Hello())#輸出 7?
# 3. 定義一個變量,給變量的賦值是個函數名,就相當于把這個變量變成一個函數了def sayHello2(name):print("你好,{},很高興再次見到你".format(name))return 1 message = sayHello2 print(message("xiaochengzi"))# 輸出 你好,xiaochengzi,很高興再次見到你 1二.函數的參數
1. 必備參數 或者 位置參數
位置參數的特點:必須要給它傳值,位置在最前面,定義了幾個位置參數,調用函數的時候就必須傳幾個參數,否在會報錯
# x,y 是位置參數,位置參數就是必須參數,函數調用時不能缺少 def add(x,y):return x+yprint(add(2,3)) #5 # 錯誤示例 def add(x,y):return x+yprint(add(2)) # TypeError: add() missing 1 required positional argument: 'y'2. 默認參數
如果不想給某個參數傳值,但是參數個數還不減少,那可以在函數聲明時設置默認參數,就是給某個參數一個默認值,
如果不傳值,函數調用時,默認就用的是設置的默認參數,如果傳值了,函數調用時就用的是傳的值
特點:默認參數的位置,一定要放到所有的位置參數的后面
# # j 定義時就給了個默認參數,如果j不傳值,就默認取0, 默認參數一定要放在所有參數的最后面 def add1(i,j=0):return i+jprint(add1(3)) # 33. 不定長參數
如果函數聲明時,還不能確定到底會有多少個參數,可以定義不定長參數
特點:1) 不定長參數用*args表示, 2) *args的類型是元組 3)它的位置必須在默認參數后面
def add2(x,y=0,*args):print(args)return x + yprint(add2(2)) # 輸出 () # 此時x=2,y =0, *args沒有傳參,是個空元組 2print(add2(4,5)) #輸出 () # 此時x=4,y =5, *args沒有傳參,是個空元組 9print(add2(1,3,5,7,9)) # 輸出 (5, 7, 9) # 此時x=1,y =3, *args是個元組,其值是(5,7,9) 4 def add2(x,y=0,*args):print(args)return x + y + sum(args) # 使用參數,要去掉*號print(add2(1,3,5,7,9))#輸出 (5, 7, 9) 254. 關鍵字參數
如果想傳的參數是字典,就可以用關鍵字參數
特點:關鍵字參數 **kargs ,其類型是字典,必須最最后面,以 a = 1的形式傳參
def add4(x,y,*args,**kwargs):print(kwargs)return x + y + sum(args) + sum(kwargs.values())print(add4(1,3,3,4,5,a=1,b=5,c=5,d=-5))# 輸出 {'a': 1, 'b': 5, 'c': 5, 'd': -5} # 此時,x=1,y=3, args=(3,4,5),kwargs = {'a': 1, 'b': 5, 'c': 5, 'd': -5}225. 形參與實參
?
?
三.函數的作用域
函數作用域的尋找順序:Local -> enclosing->global -> build-in
1. L(Local)局部作用域
變量是在函數內定義的
a = 3 # 全局作用域def scope():a = 5 # 局部作用域print(a)scope()# 輸出 5?
2. E(Enclosing)閉包函數外的函數中
見后面閉包的介紹
?
3.G (Global)全局作用域
變量是在函數外定義的,是整個文件的
a = 3def scope():print(a)scope() #輸出 34. B(Built-in) 內建作用域
Python 自帶的,預留的一些變量,函數名等
Python自帶的不太適合舉例說明
作用域的查找順序是先局部,后全局,最后再內建,如果都沒有該變量,就會報錯
def scope():print(a)scope()# NameError: name 'a' is not defined5. 作用域有兩個函數:Locals() 和 globals()
a = 3def scope():a = 5print(globals()) # 輸出 {'__name__': '__main__', '__doc__': '\n作用域生效機制\n局部 閉包函數外的函數中 全局 內建\n\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10511a470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/qiaoersun/Documents/千萬別刪/測試/Codes/testfanStudyPractice/lesson02/作用域.py', '__cached__': None, 'a': 3, 'scope': <function scope at 0x10529bd08>}暫時還沒弄明白
四.閉包(_closure_)
閉包的特點:
1. 閉包函數必須有內嵌函數
2. 內嵌函數需要引用嵌套函數的變量
3. 閉包函數必須返回內嵌函數
閉包的作用:
1. Python閉包就是裝飾器(或叫修飾器)
2. 在不改原有函數任何內容的情況下,給原有函數增加功能
def greeting(name):'''1.在greeting函數中內嵌了一個greet函數2.greeting函數的返回值是一個函數greet'''def greet():print(name)return greet # 函數的返回值是greet函數# 定義一個func變量,調用greeting函數,因為greeting函數的返回值是greet,而greet也是個函數,所以就相當于func是個函數 # 此時只是返回了greet,greet函數并沒有被調用,所以也不會有任何返回值 func = greeting('老劉')# 那么再調用func這個函數就等于是調用的下面的部分 '''def greet():print(name) ''' func() # 輸出 老劉 # greeting()其實就是greet函數,那么也可以用下面的方式調用 greeting("小貓")() # 輸出 小貓對閉包函數的公式總結
def greeting(name):# 1. greeting函數里內嵌,嵌套了一個greet函數 --> 滿足了:閉包函數必須有內嵌函數a = 5def greet():# 2.在內嵌函數里引用了嵌套函數(greeting)的變量:a 和 name, 這個變量必須是內嵌函數外層已經定義的,不能是全局變量---># 滿足了:內嵌函數必須要引用嵌套函數的變量print(name)print(a)# 3. greeting函數里返回了一個內嵌函數greet--->滿足了:函數必須返回內嵌函數return greet # 注意此處不能返回greet()# 4. 由上面3點的同時滿足,才使得greeting成為一個閉包函數# 5. 閉包函數的調用,在上面已經有了,此處略在Python里閉包其實就是裝飾器
五.裝飾器
?裝飾器的作用:就是為已經存在的對象添加額外的功能
?裝飾器的應用場景:插入日志,性能測試,事務處理,緩存,權限校驗等等
示例:計算一個函數執行用了多長時間
''' 閉包的作用: 1. 在Python閉包就是裝飾器(或叫修飾器) 2. 在不改原有函數任何內容的情況下,給原有函數增加功能利用閉包實現修飾器 '''''' 1. 計算原有函數wait()的執行時間,但是不能改wait()函數的任何代碼 2. add()函數,把add()執行結果寫入一個文件,不能改變add()函數的任何值 '''import time import random''' 解決辦法:用閉包的方式解決,那么就要把原來已經存在的功能,即函數作為參數傳遞給閉包,此處形參用func代替 閉包一定是寫在原還是的前面的 ''' # 2.用閉包的方式不改變原代碼的情況下,新增計算時間的功能 def decorator(func):def wrapper():startTime = time.time()result = func()endTime = time.time()print("測試結束,花費時間{}秒".format(endTime-startTime))return result # 上面已經執行過了result,這里為什么還要再返回一下result?不返回會有什么影響?return wrapper''' wait函數是已經存在的一段代碼,假設有一萬行,突然有個需求,要在wait上加一個功能,計算wait函數執行需要花多長時間 如果直接在wait函數上改,可能會引起其他bug,第二你也懶得看wait的代碼,一個好的解決辦法就是使用閉包,用裝飾器來解決 這個問題 '''# 1. 已有的功能 def wait():w = random.randint(5,10)print(w)time.sleep(w)print("執行wait完畢,用了{}秒".format(w))# 3. 調用閉包,獲取執行結果 a = decorator(wait) # 相當于a 就是 wrapper函數里 a() # 再調用wrapper函數, 就能得到計算的結果# 輸出 9 執行wait完畢,用了9秒 測試結束,花費時間9.005208253860474秒上面利用閉包寫好了修飾器,但是閉包的使用不是像上面那樣通過a = decorator(wait)()的方式使用的,而是通過在原有函數的上面加@閉包函數名的方式使用
import time import random# 2.用閉包的方式不改變原代碼的情況下,新增計算時間的功能 def decorator(func):def wrapper():startTime = time.time()result = func()endTime = time.time()print("測試結束,花費時間{}秒".format(endTime-startTime))return result return wrapper# 3.通過@閉包函數名的方式,實現裝飾器 @decorator # 1. 已有的功能 def wait():w = random.randint(5,10)print(w)time.sleep(w)print("執行wait完畢,用了{}秒".format(w))# 4. 直接調用原函數就可以實現功能 wait()# 輸出 10 執行wait完畢,用了10秒 測試結束,花費時間10.002923727035522秒?
# 示例2''' 已知:現有add函數 需求:add函數執行結果寫到一個文件里去 '''def writeAddtoFile(func): # 閉包的參數func,將來傳的就是原有的功能函數add,這是永遠不變的,套路,固定寫法;外面的函數傳函數名def wrapper(a,b): # 內嵌函數的參數,接受的是原函數add的參數,這也是永遠不變的,套路,固定寫法;里面的函數傳的才是參數result = func(a,b)with open("add.txt",'a',encoding='utf-8') as f:f.write(str(result)+"\n") # 換行寫入,要在寫入的內容后面 加 +"\n" f.close()return wrapper@writeAddtoFile def add(x,y):return x+yadd(5,8) add(3,5) add(1,1) # 固定寫法 def deco(func): # 固定寫法,這里的func將來接收的是adddef wrapper(*args, **kargs): # 固定寫法:這里的參數將來接收的時候 add函數的a 和 b 兩個參數result = func(args, kargs) # 新功能在內嵌函數里寫return resultreturn wrapper # 固定寫法;要把內嵌的函數返回def add(a,b):pass練習:輸入某年某月某日,判斷這一天是這一年的第幾天?
import timedef calDay(date):'''輸入某個日期,計算是這一年的第幾天:param date::return:'''# 1. 先把輸入的日期格式化fenGefu = ['/','.','-','年','月']try:for i in date:if i in fenGefu:date=date.replace(i,'-')elif i == '日':date=date.replace(i,"")# 2.利用time模塊函數得到forMatDate = time.strptime(date, '%Y-%m-%d')result = time.struct_time(forMatDate)# 3. 提取想要的結果返回days = result.tm_ydayreturn "{}是今年的地{}天".format(date, days)except Exception:print("您輸入的日期格式不對,請檢查后重新輸入")date=input("請輸入年月日:")print(calDay(date))?六.內置函數
1. 類型轉換函數
bool , int , long ,float ,bytearray str, unicode, basestring,list tuple set,dict, frozenset, complex2.文件IO
input, print, open,file, format3. 數學運算
abs,divmod, pow, sum, cmp, bin, oct, hex, chr, unichr, ord, max, min, round # 1. 求模求余 divmod(99,1) # (14,1)#2. 求冪 pow(2,3) $ 8# round()四舍五入, 有bug,慎用?
4. 集合切片
len, range, iter, next, slice(切片), enumerate, sorted, reversed?
data = ['a','b','c'] # enumerate 返回對象的下標 for i,v in enumerate(data):print(i,v)
# 輸出
0 a
1 b
2 c
5. 高階函數
高階函數:返回值是函數,或者函數的參數是函數
any(任意一個滿足條件,返回True), all(所有滿足條件,返回TRUE), map,reduce, filter, zipmap,reduce,filter是Python里很常用的三個高階函數
map(func,iter):第一個參數是個函數,第二個參數要是一個可迭代對象
# map的第一個參數是個函數,第二個參數是個可迭代對象 # map的作用:對data數據里的每個元素,分別執行函數pow # map的返回是個map對象,所以,map的兩種使用方法:1. 用list轉化, 2.用for循環 data = [1,2,3,4,5,6,7,8,9] def pow(n):return n**n# map的第一個參數是個函數,第二個參數是個可迭代對象 # map的作用:對data數據里的每個元素,分別執行函數pow # map的返回是個map對象,所以,map的兩種使用方法:1. 用list轉化, 2.用for循環# 使用list獲取map的返回值 print(list(map(pow,data))) # 輸出 [1, 4, 27, 256, 3125, 46656, 823543, 16777216, 387420489]# map函數用for循環取結果 for p in map(pow,data):print(p)# 輸出 1 4 27 256 3125 46656 823543 16777216 387420489 # 還有更簡單的,就是可以用lambda 匿名函數,替換 pow函數,就不用再定義上面的pow函數了print(map(lambda n: n**2, data))lambda 返回值:表達式reduce(function,sequence): 第一個參數是個函數,
reduce():折疊函數,
# reduce函數:折疊函數 # 作用:類似于sum(), # 函數的運行方式:data里的1和2先相加得到3,然后再用3+ data里的3,得到6,然后用6再加data里的4,依次類推,直到data的最后一個數from functools import reduce # reduce 在Python3里,要先導入才能使用 print(reduce(lambda x,y:x+y, data))# 輸出 45
filter(func, iter):過濾器
作用:filter函數作為過濾器,挑選滿足條件的數據
# filter 函數 # 作用:filter函數作為過濾器,挑選滿足條件的數據 # 從data里挑選出奇數 print(list(filter(lambda x:x % 2 !=0, data)))# 輸出 [1, 3, 5, 7, 9] # 從data里取出偶數print(list(filter(lambda x:x % 2 == 0, data )))# 輸出 [2, 4, 6, 8]6. 反射與內省
type, isinstance,issubclass,callable,staticmethod,classmethod,getattr, setattr, delattr,hasattr, super,dir,help,id,hash,object,__import__,compile,reload, repr,vars,locals,globals,eval,exec , execfile, property,memoryview?
轉載于:https://www.cnblogs.com/victorm/p/11289624.html
總結
- 上一篇: 沈阳上门回收奢侈品腕表回收聚高奢
- 下一篇: ,&#11904;问3o万房贷等