跟老齊學(xué)Python之傳說(shuō)中的函數(shù)編寫(xiě)條規(guī)
關(guān)于函數(shù)的事情,總是說(shuō)不完的,下面就羅列一些編寫(xiě)函數(shù)的注意事項(xiàng)。特別聲明,這些事項(xiàng)不是我總結(jié)的,我是從一本名字為《Learning Python》的書(shū)里面抄過(guò)來(lái)的,順便寫(xiě)成了漢語(yǔ),當(dāng)然,是按照自己的視角翻譯的,里面也夾雜了一些自己的觀點(diǎn)??垂僖部梢岳斫鉃樵从凇禠earning Python》但又有點(diǎn)兒不同。
•函數(shù)具有獨(dú)立性。也就是常說(shuō)的不要有太強(qiáng)的耦合性。要讓函數(shù)能夠獨(dú)立于外部的東西。參數(shù)和return語(yǔ)句就是實(shí)現(xiàn)這種獨(dú)立性的最好方法。
•盡量不要使用全局變量,這也是讓函數(shù)具有低耦合度的方法。全局變量雖然進(jìn)行了函數(shù)內(nèi)外通信,但是它強(qiáng)化了函數(shù)對(duì)外部的依賴(lài),常常讓函數(shù)的修改和程序調(diào)試比較麻煩。
•如果參數(shù)的對(duì)象是可變類(lèi)型的數(shù)據(jù),在函數(shù)中,不要做對(duì)它的修改操作。當(dāng)然,更多時(shí)候,參數(shù)傳入的最好是不可變的。
•函數(shù)實(shí)現(xiàn)的功能和目標(biāo)要單一化。每個(gè)函數(shù)的開(kāi)頭,都要有簡(jiǎn)短的一句話來(lái)說(shuō)明本函數(shù)的功能和目標(biāo)。
•函數(shù)不要太大,能小則小,根據(jù)前一條的原則,功能目標(biāo)單一,則代碼條數(shù)就小了。如果感覺(jué)有點(diǎn)大,看看能不能拆解開(kāi),分別為幾個(gè)函數(shù)。
•不要修改另外一個(gè)模塊文件中的變量。這跟前面的道理是一樣的,目的是降低耦合性。
小試一下遞歸
對(duì)于在python中使用遞歸,我一項(xiàng)持謹(jǐn)慎態(tài)度,能不用就不用,為什么呢?一方面深恐自己學(xué)藝不精,另外,遞歸不僅消耗資源,而且很多時(shí)候速度也不如for循環(huán)快。
不過(guò),做為程序員,遞歸還是需要了解的。這里就列舉一個(gè)簡(jiǎn)單的例子。
>>> def newsum(lst):
... if not lst:
... return 0
... else:
... return lst[0] + newsum(lst[1:])
...
>>> newsum([1,2,3])
6
這是一個(gè)對(duì)list進(jìn)行求和的函數(shù)(看官可能想到了,不是在python中有一個(gè)sum內(nèi)置函數(shù)來(lái)求和么?為什么要自己寫(xiě)呢?是的,在實(shí)際的編程中,沒(méi)有必要自己寫(xiě),用sum就可以了。這里用這個(gè)例子,純粹是為了說(shuō)明遞歸,沒(méi)有編程實(shí)踐的意義),當(dāng)然,我沒(méi)有判斷傳給函數(shù)的參數(shù)是否為完全由數(shù)字組成的list,所以,如果輸入的list中字母,就會(huì)編程這樣了:
>>> newsum([1,2,3,'q'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in newsum
File "<stdin>", line 5, in newsum
File "<stdin>", line 5, in newsum
File "<stdin>", line 5, in newsum
TypeError: cannot concatenate 'str' and 'int' objects
這就是本函數(shù)的缺憾了。但是,為了說(shuō)明遞歸,我們就顧不了這么多了。暫且忽略這個(gè)缺憾??垂僮⒁馍厦娴暮瘮?shù)中,有一句:return lst(0)+newsum(lst[1:]),在這句話中,又調(diào)用了一邊函數(shù)本身。對(duì)了,這就遞歸,在函數(shù)中調(diào)用本函數(shù)自己。當(dāng)然,區(qū)別在于傳入的參數(shù)有變化了。為了清除函數(shù)的調(diào)用流程,我們可以將每次傳入的參數(shù)打印出來(lái):
>>> def newsum(lst):
... print lst
... if not lst:
... return 0
... else:
... return lst[0] + newsum(lst[1:])
...
>>> newsum([1,2,3])
[1, 2, 3]
[2, 3]
[3]
[]
6
這就是遞歸了。
其實(shí),看官或許已經(jīng)想到了,即使不用sum,也可以用for來(lái)事項(xiàng)上述操作。
>>> lst = [1,2,3]
>>> sum_result = 0
>>> for x in lst: sum_result += x
...
>>> sum_result
6
銘記:函數(shù)是對(duì)象
還記得,在第一部分學(xué)習(xí)的時(shí)候,不斷強(qiáng)調(diào)的:變量無(wú)類(lèi)型,數(shù)據(jù)有類(lèi)型,那時(shí)候遇到的數(shù)據(jù)包括字符串、數(shù)值、列表、元組、字典、文件,這些東西,都被視為對(duì)象。函數(shù)跟它們類(lèi)似,也是對(duì)象。因此就可以像以前的對(duì)象一樣進(jìn)行賦值、傳遞給其它函數(shù)、嵌入到數(shù)據(jù)結(jié)構(gòu)、從一個(gè)函數(shù)返回給另一個(gè)函數(shù)等等面向?qū)ο蟮牟僮?。?dāng)然,函數(shù)這個(gè)對(duì)象也有特殊性,就是它可以由一個(gè)函數(shù)表達(dá)式后面的括號(hào)中的列表參數(shù)調(diào)用。
>>> def newsum(lst): #依然以這個(gè)遞歸的函數(shù)為例
... print lst
... if not lst:
... return 0
... else:
... return lst[0] + newsum(lst[1:])
...
>>> lst = [1,2,3]
>>> newsum(lst) #這是前面已經(jīng)常用的方法
[1, 2, 3]
[2, 3]
[3]
[]
6
>>> recusion_fun = newsum #通過(guò)賦值語(yǔ)句,讓變量recusion_fun也引用了函數(shù)newsum(lst)對(duì)象
>>> recusion_fun(lst) #從而變量能夠?qū)崿F(xiàn)等同函數(shù)調(diào)用的操作
[1, 2, 3]
[2, 3]
[3]
[]
6
再看一個(gè)例子,在這個(gè)例子中,一定要謹(jǐn)記函數(shù)是對(duì)象??垂僭浄瘢吭趌ist中,可以容納任何對(duì)象,那么,是否能夠容納一個(gè)函數(shù)中呢?
>>> fun_list = [(newsum,[1,2,3]),(newsum,[1,2,3,4,5])]
>>> for fun,arg in fun_list:
... fun(arg)
...
[1, 2, 3]
[2, 3]
[3]
[]
6
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[3, 4, 5]
[4, 5]
[5]
[]
15
函數(shù),真的就是對(duì)象啊。
既然是對(duì)象,就可以用dir(object)方式查看有關(guān)信息嘍:
>>> dir(newsum)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> dir(newsum.__code__)
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
>>> newsum.__code__.__doc__
'code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\nCreate a code object. Not for the faint of heart.'
>>> newsum.__code__.co_varnames
('lst',)
>>> newsum.__code__.co_argcount
1
所以,各位看官,在使用函數(shù)的時(shí)候,首先要把它放在對(duì)象的層面考量,它不是什么特殊的東西,盡管我們使用了不少篇幅講述它,但它終歸還是一個(gè)對(duì)象。
相關(guān)文章
Django中select_related和prefetch_related的用法與區(qū)別詳解
在實(shí)際的開(kāi)發(fā)中,模型之間經(jīng)常存在復(fù)雜的關(guān)聯(lián)關(guān)系,下面這篇文章主要給大家介紹了關(guān)于Django中select_related和prefetch_related的用法與區(qū)別的相關(guān)資料,需要的朋友可以參考下2022-11-11Python讀取Excel數(shù)據(jù)實(shí)現(xiàn)批量生成PPT
我們常常面臨著大量的重復(fù)性工作,通過(guò)人工方式處理往往耗時(shí)耗力易出錯(cuò)。而Python在辦公自動(dòng)化方面具有天然優(yōu)勢(shì)。本文將利用讀取Excel數(shù)據(jù)并實(shí)現(xiàn)批量生成PPT,需要的可以參考一下2022-05-05解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問(wèn)題
今天小編就為大家分享一篇解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01Python astype(np.float)函數(shù)使用方法解析
這篇文章主要介紹了Python astype(np.float)函數(shù)使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06基于Python實(shí)現(xiàn)簡(jiǎn)單的學(xué)生點(diǎn)名系統(tǒng)
現(xiàn)在的學(xué)生大部分都很積極,會(huì)主動(dòng)舉手回答問(wèn)題。但是,也會(huì)遇到一些不好的情況,比如年級(jí)越高主動(dòng)舉手的人越少,所以本文做了一個(gè)隨機(jī)的學(xué)生點(diǎn)名系統(tǒng)可以幫老師解決這些問(wèn)題2022-09-09Pytest+request+Allure實(shí)現(xiàn)接口自動(dòng)化框架
接口自動(dòng)化是指模擬程序接口層面的自動(dòng)化,由于接口不易變更,維護(hù)成本更小,所以深受各大公司的喜愛(ài),本文主要介紹了Pytest+request+Allure實(shí)現(xiàn)接口自動(dòng)化框架,感興趣的可以了解一下2021-07-07python運(yùn)用pygame庫(kù)實(shí)現(xiàn)雙人彈球小游戲
這篇文章主要為大家詳細(xì)介紹了python運(yùn)用pygame庫(kù)實(shí)現(xiàn)雙人彈球小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11python實(shí)現(xiàn)n個(gè)數(shù)中選出m個(gè)數(shù)的方法
今天小編就為大家分享一篇python實(shí)現(xiàn)n個(gè)數(shù)中選出m個(gè)數(shù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11