Python 函數(shù)
創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來(lái)公司不斷探索創(chuàng)新,始終堅(jiān)持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過(guò)去的十多年時(shí)間我們累計(jì)服務(wù)了上千家以及全國(guó)政企客戶,如活動(dòng)板房等企業(yè)單位,完善的項(xiàng)目管理流程,嚴(yán)格把控項(xiàng)目進(jìn)度與質(zhì)量監(jiān)控加上過(guò)硬的技術(shù)實(shí)力獲得客戶的一致贊美。
函數(shù)是組織好的,可重復(fù)使用的,用來(lái)實(shí)現(xiàn)單一,或相關(guān)聯(lián)功能的代碼段。
函數(shù)能提高應(yīng)用的模塊性,和代碼的重復(fù)利用率。你已經(jīng)知道Python提供了許多內(nèi)建函數(shù),比如print()。但你也可以自己創(chuàng)建函數(shù),這被叫做用戶自定義函數(shù)。
定義一個(gè)函數(shù)
你可以定義一個(gè)由自己想要功能的函數(shù),以下是簡(jiǎn)單的規(guī)則:
函數(shù)代碼塊以?def?關(guān)鍵詞開頭,后接函數(shù)標(biāo)識(shí)符名稱和圓括號(hào)()。
任何傳入?yún)?shù)和自變量必須放在圓括號(hào)中間。圓括號(hào)之間可以用于定義參數(shù)。
函數(shù)的第一行語(yǔ)句可以選擇性地使用文檔字符串—用于存放函數(shù)說(shuō)明。
函數(shù)內(nèi)容以冒號(hào)起始,并且縮進(jìn)。
return [表達(dá)式]?結(jié)束函數(shù),選擇性地返回一個(gè)值給調(diào)用方。不帶表達(dá)式的return相當(dāng)于返回 None。
語(yǔ)法
def functionname( parameters ): ? "函數(shù)_文檔字符串"
function_suite
return [expression]
默認(rèn)情況下,參數(shù)值和參數(shù)名稱是按函數(shù)聲明中定義的順序匹配起來(lái)的。
實(shí)例
以下為一個(gè)簡(jiǎn)單的Python函數(shù),它將一個(gè)字符串作為傳入?yún)?shù),再打印到標(biāo)準(zhǔn)顯示設(shè)備上。
實(shí)例(Python 2.0+)
def printme( str ): ? "打印傳入的字符串到標(biāo)準(zhǔn)顯示設(shè)備上"
print str
return
函數(shù)調(diào)用
定義一個(gè)函數(shù)只給了函數(shù)一個(gè)名稱,指定了函數(shù)里包含的參數(shù),和代碼塊結(jié)構(gòu)。
這個(gè)函數(shù)的基本結(jié)構(gòu)完成以后,你可以通過(guò)另一個(gè)函數(shù)調(diào)用執(zhí)行,也可以直接從Python提示符執(zhí)行。
如下實(shí)例調(diào)用了printme()函數(shù):
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
# 定義函數(shù)def printme( str ): ? "打印任何傳入的字符串"
print str
return
# 調(diào)用函數(shù)printme("我要調(diào)用用戶自定義函數(shù)!")printme("再次調(diào)用同一函數(shù)")
以上實(shí)例輸出結(jié)果:
我要調(diào)用用戶自定義函數(shù)!再次調(diào)用同一函數(shù)
參數(shù)傳遞
在 python 中,類型屬于對(duì)象,變量是沒(méi)有類型的:
a=[1,2,3]
a="Runoob"
以上代碼中,[1,2,3]?是 List 類型,"Runoob"?是 String 類型,而變量 a 是沒(méi)有類型,她僅僅是一個(gè)對(duì)象的引用(一個(gè)指針),可以是 List 類型對(duì)象,也可以指向 String 類型對(duì)象。
可更改(mutable)與不可更改(immutable)對(duì)象
在 python 中,strings, tuples, 和 numbers 是不可更改的對(duì)象,而 list,dict 等則是可以修改的對(duì)象。
不可變類型:變量賦值?a=5?后再賦值?a=10,這里實(shí)際是新生成一個(gè) int 值對(duì)象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,相當(dāng)于新生成了a。
可變類型:變量賦值?la=[1,2,3,4]?后再賦值?la[2]=5?則是將 list la 的第三個(gè)元素值更改,本身la沒(méi)有動(dòng),只是其內(nèi)部的一部分值被修改了。
python 函數(shù)的參數(shù)傳遞:
不可變類型:類似 c++ 的值傳遞,如 整數(shù)、字符串、元組。如fun(a),傳遞的只是a的值,沒(méi)有影響a對(duì)象本身。比如在 fun(a)內(nèi)部修改 a 的值,只是修改另一個(gè)復(fù)制的對(duì)象,不會(huì)影響 a 本身。
可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過(guò)去,修改后fun外部的la也會(huì)受影響
python 中一切都是對(duì)象,嚴(yán)格意義我們不能說(shuō)值傳遞還是引用傳遞,我們應(yīng)該說(shuō)傳不可變對(duì)象和傳可變對(duì)象。
python 傳不可變對(duì)象實(shí)例
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
def ChangeInt( a ): ? ?a = 10
b = 2ChangeInt(b)print b # 結(jié)果是 2
實(shí)例中有 int 對(duì)象 2,指向它的變量是 b,在傳遞給 ChangeInt 函數(shù)時(shí),按傳值的方式復(fù)制了變量 b,a 和 b 都指向了同一個(gè) Int 對(duì)象,在 a=10 時(shí),則新生成一個(gè) int 值對(duì)象 10,并讓 a 指向它。
傳可變對(duì)象實(shí)例
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
# 可寫函數(shù)說(shuō)明def changeme( mylist ): ? "修改傳入的列表"
mylist.append([1,2,3,4])
print "函數(shù)內(nèi)取值: ", mylist
return
# 調(diào)用changeme函數(shù)mylist = [10,20,30]changeme( mylist )print "函數(shù)外取值: ", mylist
實(shí)例中傳入函數(shù)的和在末尾添加新內(nèi)容的對(duì)象用的是同一個(gè)引用,故輸出結(jié)果如下:
函數(shù)內(nèi)取值: ?[10, 20, 30, [1, 2, 3, 4]]函數(shù)外取值: ?[10, 20, 30, [1, 2, 3, 4]]
參數(shù)
以下是調(diào)用函數(shù)時(shí)可使用的正式參數(shù)類型:
必備參數(shù)
關(guān)鍵字參數(shù)
默認(rèn)參數(shù)
不定長(zhǎng)參數(shù)
必備參數(shù)
必備參數(shù)須以正確的順序傳入函數(shù)。調(diào)用時(shí)的數(shù)量必須和聲明時(shí)的一樣。
調(diào)用printme()函數(shù),你必須傳入一個(gè)參數(shù),不然會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
#可寫函數(shù)說(shuō)明def printme( str ): ? "打印任何傳入的字符串"
print str
return
#調(diào)用printme函數(shù)printme()
以上實(shí)例輸出結(jié)果:
Traceback (most recent call last):
File "test.py", line 11, in module
printme()TypeError: printme() takes exactly 1 argument (0 given)
關(guān)鍵字參數(shù)
關(guān)鍵字參數(shù)和函數(shù)調(diào)用關(guān)系緊密,函數(shù)調(diào)用使用關(guān)鍵字參數(shù)來(lái)確定傳入的參數(shù)值。
使用關(guān)鍵字參數(shù)允許函數(shù)調(diào)用時(shí)參數(shù)的順序與聲明時(shí)不一致,因?yàn)?Python 解釋器能夠用參數(shù)名匹配參數(shù)值。
以下實(shí)例在函數(shù) printme() 調(diào)用時(shí)使用參數(shù)名:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
#可寫函數(shù)說(shuō)明def printme( str ): ? "打印任何傳入的字符串"
print str
return
#調(diào)用printme函數(shù)printme( str = "My string")
以上實(shí)例輸出結(jié)果:
My string
下例能將關(guān)鍵字參數(shù)順序不重要展示得更清楚:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
#可寫函數(shù)說(shuō)明def printinfo( name, age ): ? "打印任何傳入的字符串"
print "Name: ", name
print "Age ", age
return
#調(diào)用printinfo函數(shù)printinfo( age=50, name="miki" )
以上實(shí)例輸出結(jié)果:
Name: ?mikiAge ?50
默認(rèn)參數(shù)
調(diào)用函數(shù)時(shí),默認(rèn)參數(shù)的值如果沒(méi)有傳入,則被認(rèn)為是默認(rèn)值。下例會(huì)打印默認(rèn)的age,如果age沒(méi)有被傳入:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
#可寫函數(shù)說(shuō)明def printinfo( name, age = 35 ): ? "打印任何傳入的字符串"
print "Name: ", name
print "Age ", age
return
#調(diào)用printinfo函數(shù)printinfo( age=50, name="miki" )printinfo( name="miki" )
以上實(shí)例輸出結(jié)果:
Name: ?mikiAge ?50Name: ?mikiAge ?35
不定長(zhǎng)參數(shù)
你可能需要一個(gè)函數(shù)能處理比當(dāng)初聲明時(shí)更多的參數(shù)。這些參數(shù)叫做不定長(zhǎng)參數(shù),和上述2種參數(shù)不同,聲明時(shí)不會(huì)命名?;菊Z(yǔ)法如下:
def functionname([formal_args,] *var_args_tuple ): ? "函數(shù)_文檔字符串"
function_suite
return [expression]
加了星號(hào)(*)的變量名會(huì)存放所有未命名的變量參數(shù)。不定長(zhǎng)參數(shù)實(shí)例如下:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
# 可寫函數(shù)說(shuō)明def printinfo( arg1, *vartuple ): ? "打印任何傳入的參數(shù)"
print "輸出: "
print arg1
for var in vartuple: ? ? ?print var
return
# 調(diào)用printinfo 函數(shù)printinfo( 10 )printinfo( 70, 60, 50 )
以上實(shí)例輸出結(jié)果:
輸出:10輸出:706050
匿名函數(shù)
python 使用 lambda 來(lái)創(chuàng)建匿名函數(shù)。
lambda只是一個(gè)表達(dá)式,函數(shù)體比def簡(jiǎn)單很多。
lambda的主體是一個(gè)表達(dá)式,而不是一個(gè)代碼塊。僅僅能在lambda表達(dá)式中封裝有限的邏輯進(jìn)去。
lambda函數(shù)擁有自己的命名空間,且不能訪問(wèn)自有參數(shù)列表之外或全局命名空間里的參數(shù)。
雖然lambda函數(shù)看起來(lái)只能寫一行,卻不等同于C或C++的內(nèi)聯(lián)函數(shù),后者的目的是調(diào)用小函數(shù)時(shí)不占用棧內(nèi)存從而增加運(yùn)行效率。
語(yǔ)法
lambda函數(shù)的語(yǔ)法只包含一個(gè)語(yǔ)句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下實(shí)例:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
# 可寫函數(shù)說(shuō)明sum = lambda arg1, arg2: arg1 + arg2
# 調(diào)用sum函數(shù)print "相加后的值為 : ", sum( 10, 20 )print "相加后的值為 : ", sum( 20, 20 )
以上實(shí)例輸出結(jié)果:
相加后的值為 : ?30相加后的值為 : ?40
return 語(yǔ)句
return語(yǔ)句[表達(dá)式]退出函數(shù),選擇性地向調(diào)用方返回一個(gè)表達(dá)式。不帶參數(shù)值的return語(yǔ)句返回None。之前的例子都沒(méi)有示范如何返回?cái)?shù)值,下例便告訴你怎么做:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
# 可寫函數(shù)說(shuō)明def sum( arg1, arg2 ): ? # 返回2個(gè)參數(shù)的和."
total = arg1 + arg2
print "函數(shù)內(nèi) : ", total
return total
# 調(diào)用sum函數(shù)total = sum( 10, 20 )
以上實(shí)例輸出結(jié)果:
函數(shù)內(nèi) : ?30
變量作用域
一個(gè)程序的所有的變量并不是在哪個(gè)位置都可以訪問(wèn)的。訪問(wèn)權(quán)限決定于這個(gè)變量是在哪里賦值的。
變量的作用域決定了在哪一部分程序你可以訪問(wèn)哪個(gè)特定的變量名稱。兩種最基本的變量作用域如下:
全局變量
局部變量
全局變量和局部變量
定義在函數(shù)內(nèi)部的變量擁有一個(gè)局部作用域,定義在函數(shù)外的擁有全局作用域。
局部變量只能在其被聲明的函數(shù)內(nèi)部訪問(wèn),而全局變量可以在整個(gè)程序范圍內(nèi)訪問(wèn)。調(diào)用函數(shù)時(shí),所有在函數(shù)內(nèi)聲明的變量名稱都將被加入到作用域中。如下實(shí)例:
實(shí)例(Python 2.0+)
#!/usr/bin/python# -*- coding: UTF-8 -*-
total = 0 # 這是一個(gè)全局變量# 可寫函數(shù)說(shuō)明def sum( arg1, arg2 ): ? #返回2個(gè)參數(shù)的和."
total = arg1 + arg2 # total在這里是局部變量.
print "函數(shù)內(nèi)是局部變量 : ", total
return total
#調(diào)用sum函數(shù)sum( 10, 20 )print "函數(shù)外是全局變量 : ", total
以上實(shí)例輸出結(jié)果:
函數(shù)內(nèi)是局部變量 : ?30函數(shù)外是全局變量 : ?0
1、函數(shù)定義
①使用def關(guān)鍵字定義函數(shù)
②
def 函數(shù)名(參數(shù)1.參數(shù)2.參數(shù)3...):
"""文檔字符串,docstring,用來(lái)說(shuō)明函數(shù)的作用"""
#函數(shù)體
return 表達(dá)式
注釋的作用:說(shuō)明函數(shù)是做什么的,函數(shù)有什么功能。
③遇到冒號(hào)要縮進(jìn),冒號(hào)后面所有的縮進(jìn)的代碼塊構(gòu)成了函數(shù)體,描述了函數(shù)是做什么的,即函數(shù)的功能是什么。Python函數(shù)的本質(zhì)與數(shù)學(xué)中的函數(shù)的本質(zhì)是一致的。
2、函數(shù)調(diào)用
①函數(shù)必須先定義,才能調(diào)用,否則會(huì)報(bào)錯(cuò)。
②無(wú)參數(shù)時(shí)函數(shù)的調(diào)用:函數(shù)名(),有參數(shù)時(shí)函數(shù)的調(diào)用:函數(shù)名(參數(shù)1.參數(shù)2.……)
③不要在定義函數(shù)的時(shí)候在函數(shù)體里面調(diào)用本身,否則會(huì)出不來(lái),陷入循環(huán)調(diào)用。
④函數(shù)需要調(diào)用函數(shù)體才會(huì)被執(zhí)行,單純的只是定義函數(shù)是不會(huì)被執(zhí)行的。
⑤Debug工具中Step into進(jìn)入到調(diào)用的函數(shù)里,Step Into My Code進(jìn)入到調(diào)用的模塊里函數(shù)。
python簡(jiǎn)單的函數(shù)定義和用法實(shí)例
這篇文章主要介紹了python簡(jiǎn)單的函數(shù)定義和用法,實(shí)例分析了Python自定義函數(shù)及其使用方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
具體分析如下:
這里定義了一個(gè)溫度轉(zhuǎn)換的函數(shù)及其用法。
def convertTemp(temp, scale):
if scale == "c":
return (temp - 32.0) * (5.0/9.0)
elif scale == "f":
return temp * 9.0/5.0 + 32
temp = int(input("Enter a temperature: "))
scale = input("Enter the scale to convert to: ")
converted = convertTemp(temp, scale)
print("The converted temp is: " + str(converted))
希望本文所述對(duì)大家的Python程序設(shè)計(jì)有所幫助。
目錄
許多編程語(yǔ)言都有一個(gè)特殊的函數(shù),當(dāng)操作系統(tǒng)開始運(yùn)行程序時(shí)會(huì)自動(dòng)執(zhí)行該函數(shù)。這個(gè)函數(shù)通常被命名為main(),并且依據(jù)語(yǔ)言標(biāo)準(zhǔn)具有特定的返回類型和參數(shù)。另一方面,Python解釋器從文件頂部開始執(zhí)行腳本,并且沒(méi)有自動(dòng)執(zhí)行的特殊函數(shù)。
盡管如此,為程序的執(zhí)行定義一個(gè)起始點(diǎn)有助于理解程序是如何運(yùn)行的。Python程序員提出了幾種方式對(duì)此進(jìn)行實(shí)現(xiàn)。
本文結(jié)束時(shí),您將了解以下內(nèi)容:
Python中的基本main()函數(shù)
一些Python腳本中,包含一個(gè)函數(shù)定義和一個(gè)條件語(yǔ)句,如下所示:
此代碼中,包含一個(gè)main()函數(shù),在程序執(zhí)行時(shí)打印Hello World!。此外,還包含一個(gè)條件(或if)語(yǔ)句,用于檢查__name__的值并將其與字符串"__main__"進(jìn)行比較。當(dāng)if語(yǔ)句為True時(shí),Python解釋器將執(zhí)行main()函數(shù)。更多關(guān)于Python條件語(yǔ)句的信息可以由此獲得。
這種代碼模式在Python文件中非常常見,它將作為腳本執(zhí)行并導(dǎo)入另一個(gè)模塊。為了幫助理解這段代碼的執(zhí)行方式,首先需要了解Python解釋器如何根據(jù)代碼的執(zhí)行方式設(shè)置__name__。
Python中的執(zhí)行模式
Python解釋器執(zhí)行代碼有兩種方式:
更多內(nèi)容可參考如何運(yùn)行Python腳本。無(wú)論采用哪種方式,Python都會(huì)定義一個(gè)名為__name__的特殊變量,該變量包含一個(gè)字符串,其值取決于代碼的使用方式。
本文將如下示例文件保存為execution_methods.py,以 探索 代碼如何根據(jù)上下文改變行為:
在此文件中,定義了三個(gè)對(duì)print()函數(shù)的調(diào)用。前兩個(gè)打印一些介紹性短語(yǔ)。第三個(gè)print()會(huì)先打印短語(yǔ)The value __name__ is,之后將使用Python內(nèi)置的repr()函數(shù)打印出__name__變量。
在Python中,repr()函數(shù)將對(duì)象轉(zhuǎn)化為供解釋器讀取的形式。上述示例通過(guò)使用repr()函數(shù)來(lái)強(qiáng)調(diào)__name__的值為字符串。更多關(guān)于repr()的內(nèi)容可參考Python文檔。
在本文中,您將隨處可見文件(file),模塊(module)和腳本(script)這三個(gè)字眼。實(shí)際上,三者之間并無(wú)太大的差別。不過(guò),在強(qiáng)調(diào)代碼目的時(shí),還是存在細(xì)微的差異:
“如何運(yùn)行Python腳本”一文也討論了三者的差別。
基于命令行執(zhí)行
在這類方法中,Python腳本將通過(guò)命令行來(lái)執(zhí)行。
執(zhí)行腳本時(shí),無(wú)法與Python解釋器正在執(zhí)行的代碼交互。關(guān)于如何通過(guò)命令行執(zhí)行代碼的詳細(xì)信息對(duì)本文而言并不重要,但您可以通過(guò)展開下框閱讀更多有關(guān)Windows,Linux和macOS之間命令行差異的內(nèi)容。
命令行環(huán)境
不同的操作系統(tǒng)在使用命令行執(zhí)行代碼時(shí)存在細(xì)微的差異。
在Linux和macOS中,通常使用如下命令:
美元符號(hào)($)之前的內(nèi)容可能有所不同,具體取決于您的用戶名和計(jì)算機(jī)名稱。您鍵入的命令位于$之后。在Linux或macOS上,Python3的可執(zhí)行文件名為python3,因此可以通過(guò)輸入python3 script_name.py來(lái)運(yùn)行python腳本。
在Windows上,命令提示符通常如下所示:
根據(jù)您的用戶名,之前的內(nèi)容可能會(huì)有所不同,您輸入的命令位于之后。在Windows上,Python3的可執(zhí)行文件通常為python。因此可以通過(guò)輸入python script_name.py來(lái)運(yùn)行python腳本。
無(wú)論哪種操作系統(tǒng),本文的Python腳本的輸出結(jié)果都是相同的。因此本文以Linux和macOS為例。
使用命令行執(zhí)行execution_methods.py,如下所示:
在這個(gè)示例中,__name__具有值'__main__',其中引號(hào)(')表明該值為字符串類型。
請(qǐng)記住,在Python中,使用單引號(hào)(')和雙引號(hào)(")定義的字符串沒(méi)有區(qū)別。更多關(guān)于字符串的內(nèi)容請(qǐng)參考Python的基本數(shù)據(jù)類型。
如果在腳本中包含"shebang行"并直接執(zhí)行它(./execution_methods.py),或者使用IPython或Jupyter Notebook的%run,將會(huì)獲取相同的結(jié)果。
您還可以通過(guò)向命令行添加-m參數(shù)的方法實(shí)現(xiàn)以模塊的方式執(zhí)行。通常情況下,推薦如下方式pip: python3 -m pip install package_name。
添加-m參數(shù)將會(huì)運(yùn)行包中__main__.py的代碼。更多關(guān)于__main__.py文件的內(nèi)容可參考如何將開源Python包發(fā)布到PyPI中。
在三種情況中,__name__都具有相同的值:字符串'__main__'。
技術(shù)細(xì)節(jié):Python文檔中具體定義了__name__何時(shí)取值為'__main__'。
當(dāng)通過(guò)標(biāo)準(zhǔn)輸入,腳本或者交互提示中讀取數(shù)據(jù)時(shí),模塊的__name__將取值為'__main__'。(來(lái)源)
__name__與__doc__,__package__和其他屬性一起存儲(chǔ)在模塊的全局命名空間。更多關(guān)于屬性的信息可參考Python數(shù)據(jù)模型文檔,特別是關(guān)于模塊和包的信息,請(qǐng)參閱Python Import文檔。
導(dǎo)入模塊或解釋器
接下來(lái)是Python解釋器執(zhí)行代碼的第二種方式:導(dǎo)入。在開發(fā)模塊或腳本時(shí),可以使用import關(guān)鍵字導(dǎo)入他人已經(jīng)構(gòu)建的模塊。
在導(dǎo)入過(guò)程中,Python執(zhí)行指定模塊中定義的語(yǔ)句(但僅在第一次導(dǎo)入模塊時(shí))。要演示導(dǎo)入execution_methods.py文件的結(jié)果,需要啟動(dòng)Python解釋器,然后導(dǎo)入execution_methods.py文件:
在此代碼輸出中,Python解釋器執(zhí)行了三次print()函數(shù)調(diào)用。前兩行由于沒(méi)有變量,在輸出方面與在命令行上作為腳本執(zhí)行時(shí)完全相同。但是第三個(gè)輸出存在差異。
當(dāng)Python解釋器導(dǎo)入代碼時(shí),__name__的值與要導(dǎo)入的模塊的名稱相同。您可以通過(guò)第三行的輸出了解這一點(diǎn)。__name__的值為'execution_methods',是Python導(dǎo)入的.py文件。
注意如果您在沒(méi)有退出Python時(shí)再次導(dǎo)入模塊,將不會(huì)有輸出。
注意:更多關(guān)于導(dǎo)入在Python中如何工作的內(nèi)容請(qǐng)參考官方文檔和Python中的絕對(duì)和相對(duì)導(dǎo)入。
Main函數(shù)的最佳實(shí)踐
既然您已經(jīng)了解兩種執(zhí)行方式上的差異,那么掌握一些最佳實(shí)踐方案還是很有用的。它們將適用于編寫作為腳本運(yùn)行的代碼或者在另一個(gè)模塊導(dǎo)入的代碼。
如下是四種實(shí)踐方式:
將大部分代碼放入函數(shù)或類中
請(qǐng)記住,Python解釋器在導(dǎo)入模塊時(shí)會(huì)執(zhí)行模塊中的所有代碼。有時(shí)如果想要實(shí)現(xiàn)用戶可控的代碼,會(huì)導(dǎo)致一些副作用,例如:
在這種情況下,想要實(shí)現(xiàn)用戶控制觸發(fā)此代碼的執(zhí)行,而不是讓Python解釋器在導(dǎo)入模塊時(shí)執(zhí)行代碼。
因此,最佳方法是將大部分代碼包含在函數(shù)或類中。這是因?yàn)楫?dāng)Python解釋器遇到def或class關(guān)鍵字時(shí),它只存儲(chǔ)這些定義供以后使用,并且在用戶通知之前不會(huì)實(shí)際執(zhí)行。
將如下代碼保存在best_practices.py以證明這個(gè)想法:
在此代碼中,首先從time模塊中導(dǎo)入sleep()。
在這個(gè)示例中,參數(shù)以秒的形式傳入sleep()函數(shù)中,解釋器將暫停一段時(shí)間再運(yùn)行。隨后,使用print()函數(shù)打印關(guān)于代碼描述的語(yǔ)句。
之后,定義一個(gè)process_data()函數(shù),執(zhí)行如下五項(xiàng)操作:
在命令行中執(zhí)行
當(dāng)你將此文件作為腳本用命令行執(zhí)行時(shí)會(huì)發(fā)生什么呢?
Python解釋器將執(zhí)行函數(shù)定義之外的from time import sleep和print(),之后將創(chuàng)建函數(shù)process_data()。然后,腳本將退出而不做任何進(jìn)一步的操作,因?yàn)槟_本沒(méi)有任何執(zhí)行process_data()的代碼。
如下是這段腳本的執(zhí)行結(jié)果:
我們?cè)谶@里看到的輸出是第一個(gè)print()的結(jié)果。注意,從time導(dǎo)入和定義process_data()函數(shù)不產(chǎn)生結(jié)果。具體來(lái)說(shuō),調(diào)用定義在process_data()內(nèi)部的print()不會(huì)打印結(jié)果。
導(dǎo)入模塊或解釋器執(zhí)行
在會(huì)話(或其他模塊)中導(dǎo)入此文件時(shí),Python解釋器將執(zhí)行相同的步驟。
Python解釋器導(dǎo)入文件后,您可以使用已導(dǎo)入模塊中定義的任何變量,類或函數(shù)。為了證明這一點(diǎn),我們將使用可交互的Python解釋器。啟動(dòng)解釋器,然后鍵入import best_practices:
導(dǎo)入best_practices.py后唯一的輸出來(lái)自process_data()函數(shù)外定義的print()。導(dǎo)入模塊或解釋器執(zhí)行與基于命令行執(zhí)行類似。
使用__name__控制代碼的執(zhí)行
如何實(shí)現(xiàn)基于命令行而不使用Python解釋器導(dǎo)入文件來(lái)執(zhí)行呢?
您可以使用__name__來(lái)決定執(zhí)行上下文,并且當(dāng)__name__等于"__main__"時(shí)才執(zhí)行process_data()。在best_practices.py文件中添加如下代碼:
這段代碼添加了一個(gè)條件語(yǔ)句來(lái)檢驗(yàn)__name__的值。當(dāng)值為"__main__"時(shí),條件為True。記住當(dāng)__name__變量的特殊值為"__main__"時(shí)意味著Python解釋器會(huì)執(zhí)行腳本而不是將其導(dǎo)入。
條件語(yǔ)塊內(nèi)添加了四行代碼(第12,13,14和15行):
現(xiàn)在,在命令行中運(yùn)行best_practices.py,并觀察輸出的變化:
首先,輸出顯示了process_data()函數(shù)外的print()的調(diào)用結(jié)果。
之后,data的值被打印。因?yàn)楫?dāng)Python解釋器將文件作為腳本執(zhí)行時(shí),變量__name__具有值"__main__",因此條件語(yǔ)句被計(jì)算為True。
接下來(lái),腳本將調(diào)用process_data()并傳入data進(jìn)行修改。當(dāng)process_data執(zhí)行時(shí),將輸出一些狀態(tài)信息。最終,將輸出modified_data的值。
現(xiàn)在您可以驗(yàn)證從解釋器(或其他模塊)導(dǎo)入best_practices.py后發(fā)生的事情了。如下示例演示了這種情況:
注意,當(dāng)前結(jié)果與將條件語(yǔ)句添加到文件末尾之前相同。因?yàn)榇藭r(shí)__name__變量的值為"best_practices",因此條件語(yǔ)句結(jié)果為False,Python將不執(zhí)行process_data()。
創(chuàng)建名為main()的函數(shù)來(lái)包含要運(yùn)行的代碼
現(xiàn)在,您可以編寫作為腳本由從命令行執(zhí)行并導(dǎo)入且沒(méi)有副作用的Python代碼。接下來(lái),您將學(xué)習(xí)如何編寫代碼并使其他程序員能輕松地理解其含義。
許多語(yǔ)言,如C,C++,Java以及其他的一些語(yǔ)言,都會(huì)定義一個(gè)叫做main()的函數(shù),當(dāng)編譯程序時(shí),操作系統(tǒng)會(huì)自動(dòng)調(diào)用該函數(shù)。此函數(shù)通常被稱為入口點(diǎn)(entry point),因?yàn)樗浅绦蜻M(jìn)入執(zhí)行的起始位置。
相比之下,Python沒(méi)有一個(gè)特殊的函數(shù)作為腳本的入口點(diǎn)。實(shí)際上在Python中可以將入口點(diǎn)定義成任何名稱。
盡管Python不要求將函數(shù)命名為main(),但是最佳的做法是將入口點(diǎn)函數(shù)命名為main()。這樣方便其他程序員定位程序的起點(diǎn)。
此外,main()函數(shù)應(yīng)該包含Python解釋器執(zhí)行文件時(shí)要運(yùn)行的任何代碼。這比將代碼放入條件語(yǔ)塊中更好,因?yàn)橛脩艨梢栽趯?dǎo)入模塊時(shí)重復(fù)使用main()函數(shù)。
修改best_practices.py文件如下所示:
在這個(gè)示例中,定義了一個(gè)main()函數(shù),它包含了上面的條件語(yǔ)句塊。之后修改條件語(yǔ)塊執(zhí)行main()。如果您將此代碼作為腳本運(yùn)行或?qū)耄瑢@得與上一節(jié)相同的輸出。
在main()中調(diào)用其他函數(shù)
另一種常見的實(shí)現(xiàn)方式是在main()中調(diào)用其他函數(shù),而不是直接將代碼寫入main()。這樣做的好處在于可以實(shí)現(xiàn)將幾個(gè)獨(dú)立運(yùn)行的子任務(wù)整合。
例如,某個(gè)腳本有如下功能:
如果在單獨(dú)的函數(shù)中各自實(shí)現(xiàn)這些子任務(wù),您(或其他用戶)可以很容易地實(shí)現(xiàn)代碼重用。之后您可以在main()函數(shù)中創(chuàng)建默認(rèn)的工作流。
您可以根據(jù)自己的情況選擇是否使用此方案。將任務(wù)拆分為多個(gè)函數(shù)會(huì)使重用更容易,但會(huì)增加他人理解代碼的難度。
修改best_practices.py文件如下所示:
在此示例代碼中,文件的前10行具有與之前相同的內(nèi)容。第12行的第二個(gè)函數(shù)創(chuàng)建并返回一些示例數(shù)據(jù),第17行的第三個(gè)函數(shù)模擬將修改后的數(shù)據(jù)寫入數(shù)據(jù)庫(kù)。
第21行定義了main()函數(shù)。在此示例中,對(duì)main()做出修改,它將調(diào)用數(shù)據(jù)讀取,數(shù)據(jù)處理以及數(shù)據(jù)寫入等功能。
首先,從read_data_from_web()中創(chuàng)建data。將data作為參數(shù)傳入process_data(),之后將返回modified_data。最后,將modified_data傳入write_data_to_database()。
腳本的最后兩行是條件語(yǔ)塊用于驗(yàn)證__name__,并且如果if語(yǔ)句為True,則執(zhí)行main()。
在命令行中運(yùn)行如下所示:
根據(jù)執(zhí)行結(jié)果,Python解釋器在執(zhí)行main()函數(shù)時(shí),將依次執(zhí)行read_data_from_web(),process_data()以及write_data_to_database()。當(dāng)然,您也可以導(dǎo)入best_practices.py文件并重用process_data()作為不同的數(shù)據(jù)輸入源,如下所示:
在此示例中,導(dǎo)入了best_practices并且將其簡(jiǎn)寫為bp。
導(dǎo)入過(guò)程會(huì)導(dǎo)致Python解釋器執(zhí)行best_practices.py的全部代碼,因此輸出顯示解釋文件用途的信息。
然后,從文件中存儲(chǔ)數(shù)據(jù)而不是從Web中讀取數(shù)據(jù)。之后,可以重用best_practices.py文件中的process_data()和write_data_to_database()函數(shù)。在此情況下,可以利用代碼重寫來(lái)取代在main()函數(shù)中實(shí)現(xiàn)全部的代碼邏輯。
實(shí)踐總結(jié)
以下是Python中main()函數(shù)的四個(gè)關(guān)鍵最佳實(shí)踐:
結(jié)論
恭喜!您現(xiàn)在已經(jīng)了解如何創(chuàng)建Python main()函數(shù)了。
本文介紹了如下內(nèi)容:
現(xiàn)在,您可以開始編寫一些非常棒的關(guān)于Python main()函數(shù)代碼啦!
Python 有很多有用的內(nèi)置函數(shù), 但還是不能滿足程序員的需求, 所以需要 自定義函數(shù) 。
如何編寫 自定義函數(shù) , 需要用到 def語(yǔ)句, 函數(shù)名, 括號(hào)及參數(shù), 冒號(hào), 函數(shù)說(shuō)明,內(nèi)置縮進(jìn)編碼模塊,return 語(yǔ)句 , 其中有一些也可省略不寫,后面會(huì)慢慢介紹。
編寫函數(shù)不可或缺的元素, 一定都要寫。函數(shù)名盡量寫得簡(jiǎn)單易懂。
一般是對(duì)函數(shù)的描述說(shuō)明。
這是編寫具體的 操作命令 的地方, 如果還未想好如何編寫, 可以使用 pass 來(lái)占位,讓程序可以運(yùn)行起來(lái),防止調(diào)試出錯(cuò)。
參數(shù)放在最后講, 是因?yàn)檫@里面的東西還是很多的。首先看個(gè)例子。
如上的案例都是限制了參數(shù)個(gè)數(shù)的, 最多傳三個(gè)參數(shù) name/age/city , 但是如果有一些特例,需要傳多個(gè)參數(shù)怎么辦呢。 參數(shù)前面加個(gè) * , 變成 可變參數(shù) 。
那如果想要傳多個(gè)包含名稱的參數(shù),例如a=1,b=2,c=3......,那該怎么寫呢。參數(shù)前面加個(gè) ** , 變成 關(guān)鍵字參數(shù) 。
Python的自定義函數(shù)格式中規(guī)中矩,用def引導(dǎo)自定義函數(shù)名,用括號(hào)給出該函數(shù)的參數(shù),在冒號(hào)后換行通過(guò)縮進(jìn)確定函數(shù)體。在格式上和條件判斷語(yǔ)句有些相似。
如果函數(shù)名和變量名沖突了,相當(dāng)于重新賦值。而python解釋是從上到下的,也就是說(shuō)此時(shí)誰(shuí)在下面誰(shuí)占用這個(gè)變量名。剩下的那個(gè)就只能在內(nèi)存中等待垃圾回收了。
自定義函數(shù)的參數(shù):
按道理來(lái)說(shuō),即使Python不嚴(yán)格要求定義函數(shù)參數(shù),但這方面的知識(shí)有助于理解自定義函數(shù)中參數(shù)操作的情況,還是應(yīng)該說(shuō)明一下的。
可以簡(jiǎn)單地理解為在定義函數(shù)時(shí)括號(hào)中聲明的參數(shù)是我們?cè)诤瘮?shù)使用中會(huì)用到的參數(shù),在調(diào)用函數(shù)時(shí)括號(hào)中的變量就是參加函數(shù)運(yùn)算用到的變量,換個(gè)名字參數(shù)(用于定義)和變量(用于調(diào)用)就足以理解了。