Python學習07-函數

查看所有Python相關學習筆記

此篇文章用于記錄學習過程中接觸到的與函數有關的知識點

函數:

形參:函數創(chuàng)建時括號里的參數

實參:函數調用時括號里的參數(傳進來的參數狮惜,有具體的值)

函數文檔:函數名.__doc__ # 打印出函數文檔

def count(info):
    '''
    :param info: 格式:'姓名1,:age1,姓名2:age2瑞信,...'
    :type info:str
    :return: (maxNumAge, maxNum)
    :rtype:list
    計算字符串內哪個年齡的人數最多,并返回人數最多的年齡和該年齡的人數
    '''
    pass
a = 'hasen1 :13,tom mark : 33,hasen3:13,hasen4:13,hasen5:33,   hasen5:40'
count(a)

  • :param a -->指明參數為a
  • :type a:int -->指明參數a的類型為int
  • :return:a*2 -->指明返回的內容
  • :rtype:int -->指明返回的類型
  • 調用函數時差购,按住ctrl异逐,鼠標指向調用參數的位置可以查看該函數的參數個數忍抽、類型八孝,以及返回類型
顯示內容如下:
---def count(info)
---inferred type:(info:str) -> list
>>>print(count.__doc__) #打印查看此函數文檔
    :param info: 格式:'姓名1,:age1,姓名2:age2,...'
    :type info:str
    :return: (maxNumAge, maxNum)
    :rtype:list
    計算字符串內哪個年齡的人數最多鸠项,并返回人數最多的年齡和該年齡的人數

必選參數:避免因順序問題調用錯誤(一旦第n個參數使用了關鍵字傳參干跛,后面的都必須使用)

def SaySome(name,words):
    print(name+ '-->'+words)
SaySome(name='hasen',words='hello world')

# 執(zhí)行結果
hasen-->hello world

默認參數:為形參定義初值,調用時若忘記傳值祟绊,則使用初始值

def SaySome(name,words='hello world'):
    '某人說...'
    print(name+ '-->'+words)
SaySome(name='hasen0')
SaySome(name='hasen1',words='i love python')

# 執(zhí)行結果
hasen0-->hello world
hasen1-->i love python

可更改與不可更改的參數

所有的變量都可以理解是內存中的一個對象的“引用”楼入,而對象有兩種,“可更改(mutable)”與“不可更改(immutable)”對象牧抽。在python中 嘉熊,strings,tuples和numbers是不可更改的對象,而list,dict等則是可以修改的對象

收集參數

如果收集參數后面有其他參數扬舒,則調用其他參數時要采用關鍵字參數的調用方法记舆,否則會報錯。一般情況下呼巴,該其他參數會定義一個默認值(例如print函數中的end等)泽腮。
*args是可變參數,args接收的是一個tuple:

def func(a,b,c=0,*args):
    print(a,b,c,args)
func(1,2,3,*[1,2,3,4])
func(1,2,3,[1,2,3,4])
func(1,2,3,4)
# 執(zhí)行結果
1 2 3 (1, 2, 3, 4)
1 2 3 ([1, 2, 3, 4],)
1 2 3 (4,)
def test(*params,exp=0):
    '收集參數...'
    print('參數的長度是:',len(params))
    print('exp:',exp)
test(1,2,3,exp = 4)
test(1,2,3,4)
# 執(zhí)行結果
參數的長度是: 3
exp: 4
參數的長度是: 4
exp: 0

關鍵字參數

關鍵字參數允許你傳入0個或任意個含參數名的參數衣赶,這些關鍵字參數在函數內部自動組裝為一個dict诊赊。

  • **kw是關鍵字參數,kw接收的是一個dict府瞄。

    def person(name, age, **kw):
        print('name:', name, 'age:', age, 'other:', kw)
        
    person('Adam', 45, gender='M', job='Engineer')
    # 執(zhí)行結果
    name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
    

命名關鍵字參數

  • 如果要限制關鍵字參數的名字碧磅,就可以用命名關鍵字參數,例如遵馆,只接收city和job作為關鍵字參數鲸郊。這種方式定義的函數如下:
def person(name, age, *, city, job):
    print(name, age, city, job)
  • 和關鍵字參數kw不同,命名關鍵字參數需要一個特殊分隔符货邓,后面的參數被視為命名關鍵字參數秆撮。調用方式如下:
>>> person('Jack', 24, city='Beijing', job='Engineer')
Jack 24 Beijing Engineer
  • 如果函數定義中已經有了一個可變參數,后面跟著的命名關鍵字參數就不再需要一個特殊分隔符*了:
def person(name, age, *args, city, job):
    print(name, age, args, city, job)
  • 命名關鍵字參數必須傳入參數名换况,這和位置參數不同职辨。如果沒有傳入參數名,調用將報錯:
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given
  • 由于調用時缺少參數名city和job戈二,Python解釋器把這4個參數均視為位置參數舒裤,但person()函數僅接受2個位置參數。

  • 命名關鍵字參數可以有缺省值觉吭,從而簡化調用:

def person(name, age, *, city='Beijing', job):
    print(name, age, city, job)
  • 由于命名關鍵字參數city具有默認值腾供,調用時,可不傳入city參數:
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer
  • 使用命名關鍵字參數時鲜滩,要特別注意伴鳖,如果沒有可變參數,就必須加一個作為特殊分隔符绒北。如果缺少黎侈,Python解釋器將無法識別位置參數和命名關鍵字參數:
def person(name, age, city, job):
    # 缺少 *,city和job被視為位置參數
    pass

參數組合

在Python中定義函數闷游,可以用必選參數峻汉、默認參數、可變參數脐往、關鍵字參數和命名關鍵字參數休吠,這5種參數都可以組合使用。但是請注意业簿,參數定義的順序必須是:必選參數瘤礁、默認參數、可變參數梅尤、命名關鍵字參數和關鍵字參數柜思。

  • 比如定義一個函數岩调,包含上述若干種參數:
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
  • 在函數調用的時候,Python解釋器自動按照參數位置和參數名把對應的參數傳進去赡盘。
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
  • 最神奇的是通過一個tuple和dict号枕,你也可以調用上述函數:dict中的key只能是字符串時才可以
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}  # key值必須是字符串
>>> f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
  • 所以,對于任意函數陨享,都可以通過類似func(*args, **kw)的形式調用它葱淳,無論它的參數是如何定義的。
    注:雖然可以組合多達5種參數抛姑,但不要同時使用太多的組合赞厕,否則函數接口的可理解性很差。

返回值:

通過return返回定硝,如果return后無內容或不寫return皿桑,則函數默認返回None
如果返回多個值,則默認返回一個元組
可以人工定義為一個列表喷斋,return意味著函數的結束唁毒,函數內return后面即使有千萬條代碼也不執(zhí)行

def back():
        print(1*2)
print(back)

def back():
    return 1,'a',3.4
print(back())

def back2():
    return [1,'a',3.4]
print(back2())

# 執(zhí)行結果
2
None
(1, 'a', 3.4)
[1, 'a', 3.4]

全局變量:定義在模塊外的變量

局部變量:定義在模塊內的變量

關鍵字(global & nonlocal)

  • 在函數內定義的函數都是局部變量,函數外無法訪問;
  • 函數內可以訪問全局變量星爪,但不要修改全局變量的值;
  • 函數中如果試圖去修改全局變量浆西,此時函數會自動創(chuàng)建一個新的同名的局部變量,此時修改的其實只是函數內的該局部變量顽腾。如果一定要修改近零,可以在函數內使用global關鍵字修飾該變量
  • global關鍵字用來在函數或其他局部作用域中使用全局變量。但是如果不修改全局變量也可以不使用global關鍵字抄肖。
  • nonlocal關鍵字用來在函數或其他作用域中使用外層(非全局)變量久信。
count = 5
def MyFun():
    count = 10
    print(count)
MyFun()
print(count)

# 執(zhí)行結果
10
5
count = 5
def MyFun():
    global count
    count = 10
    print(count)
MyFun()
print(count)

# 執(zhí)行結果
10
10

內嵌函數:函數內部創(chuàng)建另一個函數,內部的這個函數就是內嵌函數

內嵌函數僅在外部函數內的作用域可以調用漓摩,在外部函數外無法調用

def fun1():
    print('fun1()正在被調用...')
    def fun2():
        print('fun2()正在被調用...')
    fun2()
fun1() 
# 執(zhí)行結果
fun1()正在被調用...
fun2()正在被調用...

閉包(詞法閉包&函數閉包)

引用了自由變量的函數裙士。這個被引用的自由變量將和這個函數一同存在,即使已經離開了創(chuàng)造它的環(huán)境也不例外管毙。
在一些語言中腿椎,在函數中可以定義另一個函數時,如果內容函數引用了外部的函數的變量夭咬,則可能產生閉包啃炸。運行時,一旦外部的函數被執(zhí)行卓舵,一個閉包就行程了南用,閉包中包含了內部函數的代碼,以及所需外部函數中的變量的引用。

def FunX(x):
    def FunY(y):
        return x * y
    return FunY

i = FunX(8)
print(type(i))
print(i(5))
print(FunX(8)(5))

# 執(zhí)行結果
<class 'function'>
40
40
def fun1():
    x = 5
    def Fun2():
        nonlocal x  #python3關鍵字裹虫,不加此行時肿嘲,調用Fun1時會報錯,因為Fun2在修改x的值
        x *= x
        return x
    return Fun2()
print(fun1())

# 執(zhí)行結果
25

lambda表達式(匿名函數)

Python寫一些執(zhí)行腳本時恒界,使用lambda就省下了定義函數的過程睦刃,比如說我們只是需要寫個簡單的腳本來管理服務器時間,我們就不需要專門定義一個函數然后在寫調用十酣,使用lambda就可以使得代碼更加精簡。
lambda不用考慮給函數命名的問題
簡化代碼的可讀性

add = lambda x,y:x+y
add(3,4)

# 執(zhí)行結果
7

兩個比較牛逼的BIF

  • filter()過濾器 filter(function or None, iterable)

1际长、第一個參數為None時耸采,返回的結果為:iterable中為True的結果
2、第一個參數為一個function時工育,返回結果為:iterable中過濾掉function的return值的結果

# 為None時
g = list(filter(None,[1,0,False,True]))
print(g)

# 執(zhí)行結果
[1, True]
# 為function時
def odd(x):
    return x % 2
temp = range(10)
show = filter(odd,temp)
h = list(show)
print(h)

# 執(zhí)行結果
[1, 3, 5, 7, 9]
# 結合lambda
j = list(filter(lambda x:x%2,range(10)))
print(j)

# 執(zhí)行結果
[1, 3, 5, 7, 9]
  • map() 映射 map(func, *iterables) --> map object

將第二個參數中的元素(序列)傳入func中虾宇,生成一個新的序列

g = list(map(lambda x:x*2,range(10)))
print(g)

# 執(zhí)行結果
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

遞歸函數

函數調用自身的行為
Python3對遞歸默認深度的設置是100層

# 手動設置遞歸深度
import sys
sys.setrecursionlimit(100000)
  • 漢諾塔游戲
  • 樹結構的定義
  • 歇爾賓斯基三角形
  • 女神自拍(遞歸)
  • 例子:寫一個求階乘的函數
    • 正整數階乘指從1乘以2乘以3乘以4一直乘到所要求的數
    • 例如所給的數是5,則階乘式是1 X 2 X 3 X 4 X 5如绸,得到的積是120嘱朽,所以120就是4的階乘
# 非遞歸方式實現
def jieC(num):
    total = 1
    for i in range(1,num+1):
        total = total* i
    return total
print(jieC(5))

# 執(zhí)行結果
120


# 遞歸方式實現
def diGui(num):
    if num == 1:
        return 1
    else:
        return num * diGui(num-1)
result = diGui(5)
print(result)

# 執(zhí)行結果
120

函數調用時加括號和不加括號的區(qū)別

  • 不帶括號時,調用的是這個函數本身 怔接,是整個函數體搪泳,是一個函數對象,不須等該函數執(zhí)行完成
  • 帶括號(參數或者無參)扼脐,調用的是函數的執(zhí)行結果岸军,須等該函數執(zhí)行完成的結果
def test():
    a = 'hello dddddd'
    return a
print(test)
print(test())

# 執(zhí)行結果
<function test at 0x101bcbe18>
hello dddddd
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瓦侮,隨后出現的幾起案子艰赞,更是在濱河造成了極大的恐慌,老刑警劉巖肚吏,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件方妖,死亡現場離奇詭異,居然都是意外死亡罚攀,警方通過查閱死者的電腦和手機党觅,發(fā)現死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坞生,“玉大人仔役,你說我怎么就攤上這事∈羌海” “怎么了又兵?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我沛厨,道長宙地,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任逆皮,我火速辦了婚禮宅粥,結果婚禮上,老公的妹妹穿的比我還像新娘电谣。我一直安慰自己秽梅,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布剿牺。 她就那樣靜靜地躺著企垦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天傻唾,我揣著相機與錄音,去河邊找鬼荧降。 笑死,一個胖子當著我的面吹牛攒读,可吹牛的內容都是我干的朵诫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼整陌,長吁一口氣:“原來是場噩夢啊……” “哼拗窃!你這毒婦竟也來了?” 一聲冷哼從身側響起泌辫,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤随夸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后震放,有當地人在樹林里發(fā)現了一具尸體宾毒,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年殿遂,在試婚紗的時候發(fā)現自己被綠了诈铛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡墨礁,死狀恐怖幢竹,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情恩静,我是刑警寧澤焕毫,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布蹲坷,位于F島的核電站,受9級特大地震影響邑飒,放射性物質發(fā)生泄漏循签。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一疙咸、第九天 我趴在偏房一處隱蔽的房頂上張望县匠。 院中可真熱鬧,春花似錦撒轮、人聲如沸乞旦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杆查。三九已至,卻和暖如春臀蛛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背崖蜜。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工浊仆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人豫领。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓抡柿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親等恐。 傳聞我的和親對象是個殘疾皇子洲劣,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348