目錄

10年積累的網(wǎng)站設(shè)計制作、成都網(wǎng)站設(shè)計經(jīng)驗,可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計后付款的網(wǎng)站建設(shè)流程,更有鐵西免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
許多編程語言都有一個特殊的函數(shù),當(dāng)操作系統(tǒng)開始運(yùn)行程序時會自動執(zhí)行該函數(shù)。這個函數(shù)通常被命名為main(),并且依據(jù)語言標(biāo)準(zhǔn)具有特定的返回類型和參數(shù)。另一方面,Python解釋器從文件頂部開始執(zhí)行腳本,并且沒有自動執(zhí)行的特殊函數(shù)。
盡管如此,為程序的執(zhí)行定義一個起始點(diǎn)有助于理解程序是如何運(yùn)行的。Python程序員提出了幾種方式對此進(jìn)行實現(xiàn)。
本文結(jié)束時,您將了解以下內(nèi)容:
Python中的基本main()函數(shù)
一些Python腳本中,包含一個函數(shù)定義和一個條件語句,如下所示:
此代碼中,包含一個main()函數(shù),在程序執(zhí)行時打印Hello World!。此外,還包含一個條件(或if)語句,用于檢查__name__的值并將其與字符串"__main__"進(jìn)行比較。當(dāng)if語句為True時,Python解釋器將執(zhí)行main()函數(shù)。更多關(guān)于Python條件語句的信息可以由此獲得。
這種代碼模式在Python文件中非常常見,它將作為腳本執(zhí)行并導(dǎo)入另一個模塊。為了幫助理解這段代碼的執(zhí)行方式,首先需要了解Python解釋器如何根據(jù)代碼的執(zhí)行方式設(shè)置__name__。
Python中的執(zhí)行模式
Python解釋器執(zhí)行代碼有兩種方式:
更多內(nèi)容可參考如何運(yùn)行Python腳本。無論采用哪種方式,Python都會定義一個名為__name__的特殊變量,該變量包含一個字符串,其值取決于代碼的使用方式。
本文將如下示例文件保存為execution_methods.py,以 探索 代碼如何根據(jù)上下文改變行為:
在此文件中,定義了三個對print()函數(shù)的調(diào)用。前兩個打印一些介紹性短語。第三個print()會先打印短語The value __name__ is,之后將使用Python內(nèi)置的repr()函數(shù)打印出__name__變量。
在Python中,repr()函數(shù)將對象轉(zhuǎn)化為供解釋器讀取的形式。上述示例通過使用repr()函數(shù)來強(qiáng)調(diào)__name__的值為字符串。更多關(guān)于repr()的內(nèi)容可參考Python文檔。
在本文中,您將隨處可見文件(file),模塊(module)和腳本(script)這三個字眼。實際上,三者之間并無太大的差別。不過,在強(qiáng)調(diào)代碼目的時,還是存在細(xì)微的差異:
“如何運(yùn)行Python腳本”一文也討論了三者的差別。
基于命令行執(zhí)行
在這類方法中,Python腳本將通過命令行來執(zhí)行。
執(zhí)行腳本時,無法與Python解釋器正在執(zhí)行的代碼交互。關(guān)于如何通過命令行執(zhí)行代碼的詳細(xì)信息對本文而言并不重要,但您可以通過展開下框閱讀更多有關(guān)Windows,Linux和macOS之間命令行差異的內(nèi)容。
命令行環(huán)境
不同的操作系統(tǒng)在使用命令行執(zhí)行代碼時存在細(xì)微的差異。
在Linux和macOS中,通常使用如下命令:
美元符號($)之前的內(nèi)容可能有所不同,具體取決于您的用戶名和計算機(jī)名稱。您鍵入的命令位于$之后。在Linux或macOS上,Python3的可執(zhí)行文件名為python3,因此可以通過輸入python3 script_name.py來運(yùn)行python腳本。
在Windows上,命令提示符通常如下所示:
根據(jù)您的用戶名,之前的內(nèi)容可能會有所不同,您輸入的命令位于之后。在Windows上,Python3的可執(zhí)行文件通常為python。因此可以通過輸入python script_name.py來運(yùn)行python腳本。
無論哪種操作系統(tǒng),本文的Python腳本的輸出結(jié)果都是相同的。因此本文以Linux和macOS為例。
使用命令行執(zhí)行execution_methods.py,如下所示:
在這個示例中,__name__具有值'__main__',其中引號(')表明該值為字符串類型。
請記住,在Python中,使用單引號(')和雙引號(")定義的字符串沒有區(qū)別。更多關(guān)于字符串的內(nèi)容請參考Python的基本數(shù)據(jù)類型。
如果在腳本中包含"shebang行"并直接執(zhí)行它(./execution_methods.py),或者使用IPython或Jupyter Notebook的%run,將會獲取相同的結(jié)果。
您還可以通過向命令行添加-m參數(shù)的方法實現(xiàn)以模塊的方式執(zhí)行。通常情況下,推薦如下方式pip: python3 -m pip install package_name。
添加-m參數(shù)將會運(yùn)行包中__main__.py的代碼。更多關(guān)于__main__.py文件的內(nèi)容可參考如何將開源Python包發(fā)布到PyPI中。
在三種情況中,__name__都具有相同的值:字符串'__main__'。
技術(shù)細(xì)節(jié):Python文檔中具體定義了__name__何時取值為'__main__'。
當(dāng)通過標(biāo)準(zhǔn)輸入,腳本或者交互提示中讀取數(shù)據(jù)時,模塊的__name__將取值為'__main__'。(來源)
__name__與__doc__,__package__和其他屬性一起存儲在模塊的全局命名空間。更多關(guān)于屬性的信息可參考Python數(shù)據(jù)模型文檔,特別是關(guān)于模塊和包的信息,請參閱Python Import文檔。
導(dǎo)入模塊或解釋器
接下來是Python解釋器執(zhí)行代碼的第二種方式:導(dǎo)入。在開發(fā)模塊或腳本時,可以使用import關(guān)鍵字導(dǎo)入他人已經(jīng)構(gòu)建的模塊。
在導(dǎo)入過程中,Python執(zhí)行指定模塊中定義的語句(但僅在第一次導(dǎo)入模塊時)。要演示導(dǎo)入execution_methods.py文件的結(jié)果,需要啟動Python解釋器,然后導(dǎo)入execution_methods.py文件:
在此代碼輸出中,Python解釋器執(zhí)行了三次print()函數(shù)調(diào)用。前兩行由于沒有變量,在輸出方面與在命令行上作為腳本執(zhí)行時完全相同。但是第三個輸出存在差異。
當(dāng)Python解釋器導(dǎo)入代碼時,__name__的值與要導(dǎo)入的模塊的名稱相同。您可以通過第三行的輸出了解這一點(diǎn)。__name__的值為'execution_methods',是Python導(dǎo)入的.py文件。
注意如果您在沒有退出Python時再次導(dǎo)入模塊,將不會有輸出。
注意:更多關(guān)于導(dǎo)入在Python中如何工作的內(nèi)容請參考官方文檔和Python中的絕對和相對導(dǎo)入。
Main函數(shù)的最佳實踐
既然您已經(jīng)了解兩種執(zhí)行方式上的差異,那么掌握一些最佳實踐方案還是很有用的。它們將適用于編寫作為腳本運(yùn)行的代碼或者在另一個模塊導(dǎo)入的代碼。
如下是四種實踐方式:
將大部分代碼放入函數(shù)或類中
請記住,Python解釋器在導(dǎo)入模塊時會執(zhí)行模塊中的所有代碼。有時如果想要實現(xiàn)用戶可控的代碼,會導(dǎo)致一些副作用,例如:
在這種情況下,想要實現(xiàn)用戶控制觸發(fā)此代碼的執(zhí)行,而不是讓Python解釋器在導(dǎo)入模塊時執(zhí)行代碼。
因此,最佳方法是將大部分代碼包含在函數(shù)或類中。這是因為當(dāng)Python解釋器遇到def或class關(guān)鍵字時,它只存儲這些定義供以后使用,并且在用戶通知之前不會實際執(zhí)行。
將如下代碼保存在best_practices.py以證明這個想法:
在此代碼中,首先從time模塊中導(dǎo)入sleep()。
在這個示例中,參數(shù)以秒的形式傳入sleep()函數(shù)中,解釋器將暫停一段時間再運(yùn)行。隨后,使用print()函數(shù)打印關(guān)于代碼描述的語句。
之后,定義一個process_data()函數(shù),執(zhí)行如下五項操作:
在命令行中執(zhí)行
當(dāng)你將此文件作為腳本用命令行執(zhí)行時會發(fā)生什么呢?
Python解釋器將執(zhí)行函數(shù)定義之外的from time import sleep和print(),之后將創(chuàng)建函數(shù)process_data()。然后,腳本將退出而不做任何進(jìn)一步的操作,因為腳本沒有任何執(zhí)行process_data()的代碼。
如下是這段腳本的執(zhí)行結(jié)果:
我們在這里看到的輸出是第一個print()的結(jié)果。注意,從time導(dǎo)入和定義process_data()函數(shù)不產(chǎn)生結(jié)果。具體來說,調(diào)用定義在process_data()內(nèi)部的print()不會打印結(jié)果。
導(dǎo)入模塊或解釋器執(zhí)行
在會話(或其他模塊)中導(dǎo)入此文件時,Python解釋器將執(zhí)行相同的步驟。
Python解釋器導(dǎo)入文件后,您可以使用已導(dǎo)入模塊中定義的任何變量,類或函數(shù)。為了證明這一點(diǎn),我們將使用可交互的Python解釋器。啟動解釋器,然后鍵入import best_practices:
導(dǎo)入best_practices.py后唯一的輸出來自process_data()函數(shù)外定義的print()。導(dǎo)入模塊或解釋器執(zhí)行與基于命令行執(zhí)行類似。
使用__name__控制代碼的執(zhí)行
如何實現(xiàn)基于命令行而不使用Python解釋器導(dǎo)入文件來執(zhí)行呢?
您可以使用__name__來決定執(zhí)行上下文,并且當(dāng)__name__等于"__main__"時才執(zhí)行process_data()。在best_practices.py文件中添加如下代碼:
這段代碼添加了一個條件語句來檢驗__name__的值。當(dāng)值為"__main__"時,條件為True。記住當(dāng)__name__變量的特殊值為"__main__"時意味著Python解釋器會執(zhí)行腳本而不是將其導(dǎo)入。
條件語塊內(nèi)添加了四行代碼(第12,13,14和15行):
現(xiàn)在,在命令行中運(yùn)行best_practices.py,并觀察輸出的變化:
首先,輸出顯示了process_data()函數(shù)外的print()的調(diào)用結(jié)果。
之后,data的值被打印。因為當(dāng)Python解釋器將文件作為腳本執(zhí)行時,變量__name__具有值"__main__",因此條件語句被計算為True。
接下來,腳本將調(diào)用process_data()并傳入data進(jìn)行修改。當(dāng)process_data執(zhí)行時,將輸出一些狀態(tài)信息。最終,將輸出modified_data的值。
現(xiàn)在您可以驗證從解釋器(或其他模塊)導(dǎo)入best_practices.py后發(fā)生的事情了。如下示例演示了這種情況:
注意,當(dāng)前結(jié)果與將條件語句添加到文件末尾之前相同。因為此時__name__變量的值為"best_practices",因此條件語句結(jié)果為False,Python將不執(zhí)行process_data()。
創(chuàng)建名為main()的函數(shù)來包含要運(yùn)行的代碼
現(xiàn)在,您可以編寫作為腳本由從命令行執(zhí)行并導(dǎo)入且沒有副作用的Python代碼。接下來,您將學(xué)習(xí)如何編寫代碼并使其他程序員能輕松地理解其含義。
許多語言,如C,C++,Java以及其他的一些語言,都會定義一個叫做main()的函數(shù),當(dāng)編譯程序時,操作系統(tǒng)會自動調(diào)用該函數(shù)。此函數(shù)通常被稱為入口點(diǎn)(entry point),因為它是程序進(jìn)入執(zhí)行的起始位置。
相比之下,Python沒有一個特殊的函數(shù)作為腳本的入口點(diǎn)。實際上在Python中可以將入口點(diǎn)定義成任何名稱。
盡管Python不要求將函數(shù)命名為main(),但是最佳的做法是將入口點(diǎn)函數(shù)命名為main()。這樣方便其他程序員定位程序的起點(diǎn)。
此外,main()函數(shù)應(yīng)該包含Python解釋器執(zhí)行文件時要運(yùn)行的任何代碼。這比將代碼放入條件語塊中更好,因為用戶可以在導(dǎo)入模塊時重復(fù)使用main()函數(shù)。
修改best_practices.py文件如下所示:
在這個示例中,定義了一個main()函數(shù),它包含了上面的條件語句塊。之后修改條件語塊執(zhí)行main()。如果您將此代碼作為腳本運(yùn)行或?qū)耄瑢@得與上一節(jié)相同的輸出。
在main()中調(diào)用其他函數(shù)
另一種常見的實現(xiàn)方式是在main()中調(diào)用其他函數(shù),而不是直接將代碼寫入main()。這樣做的好處在于可以實現(xiàn)將幾個獨(dú)立運(yùn)行的子任務(wù)整合。
例如,某個腳本有如下功能:
如果在單獨(dú)的函數(shù)中各自實現(xiàn)這些子任務(wù),您(或其他用戶)可以很容易地實現(xiàn)代碼重用。之后您可以在main()函數(shù)中創(chuàng)建默認(rèn)的工作流。
您可以根據(jù)自己的情況選擇是否使用此方案。將任務(wù)拆分為多個函數(shù)會使重用更容易,但會增加他人理解代碼的難度。
修改best_practices.py文件如下所示:
在此示例代碼中,文件的前10行具有與之前相同的內(nèi)容。第12行的第二個函數(shù)創(chuàng)建并返回一些示例數(shù)據(jù),第17行的第三個函數(shù)模擬將修改后的數(shù)據(jù)寫入數(shù)據(jù)庫。
第21行定義了main()函數(shù)。在此示例中,對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()。
腳本的最后兩行是條件語塊用于驗證__name__,并且如果if語句為True,則執(zhí)行main()。
在命令行中運(yùn)行如下所示:
根據(jù)執(zhí)行結(jié)果,Python解釋器在執(zhí)行main()函數(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并且將其簡寫為bp。
導(dǎo)入過程會導(dǎo)致Python解釋器執(zhí)行best_practices.py的全部代碼,因此輸出顯示解釋文件用途的信息。
然后,從文件中存儲數(shù)據(jù)而不是從Web中讀取數(shù)據(jù)。之后,可以重用best_practices.py文件中的process_data()和write_data_to_database()函數(shù)。在此情況下,可以利用代碼重寫來取代在main()函數(shù)中實現(xiàn)全部的代碼邏輯。
實踐總結(jié)
以下是Python中main()函數(shù)的四個關(guān)鍵最佳實踐:
結(jié)論
恭喜!您現(xiàn)在已經(jīng)了解如何創(chuàng)建Python main()函數(shù)了。
本文介紹了如下內(nèi)容:
現(xiàn)在,您可以開始編寫一些非常棒的關(guān)于Python main()函數(shù)代碼啦!
為了把類中的變量傳遞給類中的函數(shù),我們需要用到3個特定格式
① 第一個格式 @classmethod 的中文意思就是“類方法”,@classmethod聲明了函數(shù)1是類方法,這樣才能允許函數(shù)1使用類屬性中的數(shù)據(jù)。
② 第二個格式 cls 的意思是class的縮寫。如果類方法函數(shù)1想使用類屬性(也就是類中的變量),就要寫上cls為函數(shù)1的第一個參數(shù),也就是把這個類作為參數(shù)傳給自己,這樣就能被允許使用類中的數(shù)據(jù)。
③ 第三個格式是 cls.變量 。類方法想使用類屬性的時候,需要在這些變量名稱前加上cls. 這就好比類方法和類之間的約法三章,所以但凡有任何格式錯誤都會報錯。
如果缺①,即缺了“@classmethod”,類方法就不能直接利用類中的屬性,于是報錯
你好:
a是A類里面的一個函數(shù):
因此:
aa=A()
aa.a()
這樣就行 了。
首先來看一個函數(shù)間的調(diào)用
類方法:
執(zhí)行結(jié)果:
metaclass能有什么用處,先來個感性的認(rèn)識:
1.1 在wiki上面,metaclass是這樣定義的:In object-oriented programming,
a metaclass is a class whose instances are classes.
Just as an ordinary class defines the behavior of certain objects,
a metaclass defines the behavior of certain classes and their instances.
也就是說metaclass的實例化結(jié)果是類,而class實例化的結(jié)果是instance。我是這么理解的:
metaclass是類似創(chuàng)建類的模板,所有的類都是通過他來create的(調(diào)用 new ),這使得你可以自由的控制
創(chuàng)建類的那個過程,實現(xiàn)你所需要的功能。
當(dāng)然你也可以用函數(shù)的方式(下文會講)
4.1 用類的形式
4.1.1 類繼承于type, 例如: class Meta(type):pass
4.1.2 將需要使用metaclass來構(gòu)建class的類的 metaclass 屬性(不需要顯示聲明,直接有的了)賦值為Meta(繼承于type的類)
4.2 用函數(shù)的形式
4.2.1 構(gòu)建一個函數(shù),例如叫metaclass_new, 需要3個參數(shù):name, bases, attrs,
name: 類的名字
bases: 基類,通常是tuple類型
attrs: dict類型,就是類的屬性或者函數(shù)
4.2.2 將需要使用metaclass來構(gòu)建class的類的 metaclass 屬性(不需要顯示聲明,直接有的了)賦值為函數(shù)metaclas_new
5.1 basic
metaclass的原理其實是這樣的:當(dāng)定義好類之后,創(chuàng)建類的時候其實是調(diào)用了type的 new 方法為這個類分配內(nèi)存空間,創(chuàng)建
好了之后再調(diào)用type的 init 方法初始化(做一些賦值等)。所以metaclass的所有magic其實就在于這個 new 方法里面了。
說說這個方法: new (cls, name, bases, attrs)
cls: 將要創(chuàng)建的類,類似與self,但是self指向的是instance,而這里cls指向的是class
name: 類的名字,也就是我們通常用類名. name 獲取的。
bases: 基類
attrs: 屬性的dict。dict的內(nèi)容可以是變量(類屬性),也可以是函數(shù)(類方法)。
所以在創(chuàng)建類的過程,我們可以在這個函數(shù)里面修改name,bases,attrs的值來自由的達(dá)到我們的功能。這里常用的配合方法是
getattr和setattr(just an advice)
下面實現(xiàn)python中在一個類中調(diào)用另一個類的函數(shù)方法
或者下面來一個號理解的例子
執(zhí)行結(jié)果:
先來介紹內(nèi)部類與外部類是什么?
看源碼解析:
內(nèi)部類調(diào)用外部類的類屬性和類方法
參考文獻(xiàn)1
參考文獻(xiàn)2
參考文獻(xiàn)3
類,class,用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。
函數(shù),是組織好的,可重復(fù)使用的,用來實現(xiàn)單一,或相關(guān)聯(lián)功能的代碼段。
函數(shù)能提高應(yīng)用的模塊性,和代碼的重復(fù)利用率。你已經(jīng)知道python提供了許多內(nèi)建函數(shù),比如print()。但你也可以自己創(chuàng)建函數(shù),這被叫作用戶自定義函數(shù)。
python語言中類和函數(shù)的區(qū)別
1、規(guī)則不同
類是一種引用數(shù)據(jù)類型,類似于byte、short、int(char)、long、float、double等基本數(shù)據(jù)類型;
函數(shù)必須聲明后才可以被調(diào)用,調(diào)用格式為:函數(shù)名(實參)調(diào)用時函數(shù)名后的小括號中的實參必須和聲明函數(shù)時的函數(shù)括號中的形參個數(shù)相同。
2、主體不同
類是面向?qū)ο蟪绦蛟O(shè)計實現(xiàn)信息封裝的基礎(chǔ);
函數(shù)是指一段在一起的、可以做某一件事的子程序。
3、特點(diǎn)不同
類是一種用戶定義的引用數(shù)據(jù)類型,也稱類類型,每個類包含數(shù)據(jù)說明和一組操作數(shù)據(jù)或者傳遞消息的函數(shù),類的實例稱為對象;
函數(shù)分為全局函數(shù)、全局靜態(tài)函數(shù),在類中還可以定義構(gòu)造函數(shù)、析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、成員函數(shù)、友元函數(shù)、運(yùn)算符重載函數(shù)、內(nèi)聯(lián)函數(shù)等。
標(biāo)題名稱:python類里面寫函數(shù) python中函數(shù)怎么寫
文章地址:http://chinadenli.net/article38/dodpopp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、網(wǎng)站內(nèi)鏈、面包屑導(dǎo)航、服務(wù)器托管、網(wǎng)站導(dǎo)航、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)