導航:首頁 > 編程語言 > python動態創建函數

python動態創建函數

發布時間:2024-03-04 00:36:14

Ⅰ 在python中定義Main函數

目錄

許多編程語言都有一個特殊的函數,當操作系統開始運行程序時會自動執行該函數。這個函數通常被命名為main(),並且依據語言標准具有特定的返回類型和參數。另一方面,Python解釋器從文件頂部開始執行腳本,並且沒有自動執行的特殊函數。

盡管如此,為程序的執行定義一個起始點有助於理解程序是如何運行的。Python程序員提出了幾種方式對此進行實現。

本文結束時,您將了解以下內容:

Python中的基本main()函數

一些Python腳本中,包含一個函數定義和一個條件語句,如下所示:

此代碼中,包含一個main()函數,在程序執行時列印Hello World!。此外,還包含一個條件(或if)語句,用於檢查__name__的值並將其與字元串"__main__"進行比較。當if語句為True時,Python解釋器將執行main()函數。更多關於Python條件語句的信息可以由此獲得。

這種代碼模式在Python文件中非常常見,它將作為腳本執行並導入另一個模塊。為了幫助理解這段代碼的執行方式,首先需要了解Python解釋器如何根據代碼的執行方式設置__name__。

Python中的執行模式

Python解釋器執行代碼有兩種方式:

更多內容可參考如何運行Python腳本。無論採用哪種方式,Python都會定義一個名為__name__的特殊變數,該變數包含一個字元串,其值取決於代碼的使用方式。

本文將如下示例文件保存為execution_methods.py,以 探索 代碼如何根據上下文改變行為:

在此文件中,定義了三個對print()函數的調用。前兩個列印一些介紹性短語。第三個print()會先列印短語The value __name__ is,之後將使用Python內置的repr()函數列印出__name__變數。

在Python中,repr()函數將對象轉化為供解釋器讀取的形式。上述示例通過使用repr()函數來強調__name__的值為字元串。更多關於repr()的內容可參考Python文檔。

在本文中,您將隨處可見文件(file),模塊(mole)和腳本(script)這三個字眼。實際上,三者之間並無太大的差別。不過,在強調代碼目的時,還是存在細微的差異:

「如何運行Python腳本」一文也討論了三者的差別。

基於命令行執行

在這類方法中,Python腳本將通過命令行來執行。

執行腳本時,無法與Python解釋器正在執行的代碼交互。關於如何通過命令行執行代碼的詳細信息對本文而言並不重要,但您可以通過展開下框閱讀更多有關Windows,Linux和macOS之間命令行差異的內容。

命令行環境

不同的操作系統在使用命令行執行代碼時存在細微的差異。

在Linux和macOS中,通常使用如下命令:

美元符號($)之前的內容可能有所不同,具體取決於您的用戶名和計算機名稱。您鍵入的命令位於$之後。在Linux或macOS上,Python3的可執行文件名為python3,因此可以通過輸入python3 script_name.py來運行python腳本。

在Windows上,命令提示符通常如下所示:

根據您的用戶名,>之前的內容可能會有所不同,您輸入的命令位於>之後。在Windows上,Python3的可執行文件通常為python。因此可以通過輸入python script_name.py來運行python腳本。

無論哪種操作系統,本文的Python腳本的輸出結果都是相同的。因此本文以Linux和macOS為例。

使用命令行執行execution_methods.py,如下所示:

在這個示例中,__name__具有值'__main__',其中引號(')表明該值為字元串類型。

請記住,在Python中,使用單引號(')和雙引號(")定義的字元串沒有區別。更多關於字元串的內容請參考Python的基本數據類型。

如果在腳本中包含"shebang行"並直接執行它(./execution_methods.py),或者使用IPython或Jupyter Notebook的%run,將會獲取相同的結果。

您還可以通過向命令行添加-m參數的方法實現以模塊的方式執行。通常情況下,推薦如下方式pip: python3 -m pip install package_name。

添加-m參數將會運行包中__main__.py的代碼。更多關於__main__.py文件的內容可參考如何將開源Python包發布到PyPI中。

在三種情況中,__name__都具有相同的值:字元串'__main__'。

技術細節:Python文檔中具體定義了__name__何時取值為'__main__'。

當通過標准輸入,腳本或者交互提示中讀取數據時,模塊的__name__將取值為'__main__'。(來源)

__name__與__doc__,__package__和其他屬性一起存儲在模塊的全局命名空間。更多關於屬性的信息可參考Python數據模型文檔,特別是關於模塊和包的信息,請參閱Python Import文檔。

導入模塊或解釋器

接下來是Python解釋器執行代碼的第二種方式:導入。在開發模塊或腳本時,可以使用import關鍵字導入他人已經構建的模塊。

在導入過程中,Python執行指定模塊中定義的語句(但僅在第一次導入模塊時)。要演示導入execution_methods.py文件的結果,需要啟動Python解釋器,然後導入execution_methods.py文件:

在此代碼輸出中,Python解釋器執行了三次print()函數調用。前兩行由於沒有變數,在輸出方面與在命令行上作為腳本執行時完全相同。但是第三個輸出存在差異。

當Python解釋器導入代碼時,__name__的值與要導入的模塊的名稱相同。您可以通過第三行的輸出了解這一點。__name__的值為'execution_methods',是Python導入的.py文件。

注意如果您在沒有退出Python時再次導入模塊,將不會有輸出。

注意:更多關於導入在Python中如何工作的內容請參考官方文檔和Python中的絕對和相對導入。

Main函數的最佳實踐

既然您已經了解兩種執行方式上的差異,那麼掌握一些最佳實踐方案還是很有用的。它們將適用於編寫作為腳本運行的代碼或者在另一個模塊導入的代碼。

如下是四種實踐方式:

將大部分代碼放入函數或類中

請記住,Python解釋器在導入模塊時會執行模塊中的所有代碼。有時如果想要實現用戶可控的代碼,會導致一些副作用,例如:

在這種情況下,想要實現用戶控制觸發此代碼的執行,而不是讓Python解釋器在導入模塊時執行代碼。

因此,最佳方法是將大部分代碼包含在函數或類中。這是因為當Python解釋器遇到def或class關鍵字時,它只存儲這些定義供以後使用,並且在用戶通知之前不會實際執行。

將如下代碼保存在best_practices.py以證明這個想法:

在此代碼中,首先從time模塊中導入sleep()。

在這個示例中,參數以秒的形式傳入sleep()函數中,解釋器將暫停一段時間再運行。隨後,使用print()函數列印關於代碼描述的語句。

之後,定義一個process_data()函數,執行如下五項操作:

在命令行中執行

當你將此文件作為腳本用命令行執行時會發生什麼呢?

Python解釋器將執行函數定義之外的from time import sleep和print(),之後將創建函數process_data()。然後,腳本將退出而不做任何進一步的操作,因為腳本沒有任何執行process_data()的代碼。

如下是這段腳本的執行結果:

我們在這里看到的輸出是第一個print()的結果。注意,從time導入和定義process_data()函數不產生結果。具體來說,調用定義在process_data()內部的print()不會列印結果。

導入模塊或解釋器執行

在會話(或其他模塊)中導入此文件時,Python解釋器將執行相同的步驟。

Python解釋器導入文件後,您可以使用已導入模塊中定義的任何變數,類或函數。為了證明這一點,我們將使用可交互的Python解釋器。啟動解釋器,然後鍵入import best_practices:

導入best_practices.py後唯一的輸出來自process_data()函數外定義的print()。導入模塊或解釋器執行與基於命令行執行類似。

使用__name__控制代碼的執行

如何實現基於命令行而不使用Python解釋器導入文件來執行呢?

您可以使用__name__來決定執行上下文,並且當__name__等於"__main__"時才執行process_data()。在best_practices.py文件中添加如下代碼:

這段代碼添加了一個條件語句來檢驗__name__的值。當值為"__main__"時,條件為True。記住當__name__變數的特殊值為"__main__"時意味著Python解釋器會執行腳本而不是將其導入。

條件語塊內添加了四行代碼(第12,13,14和15行):

現在,在命令行中運行best_practices.py,並觀察輸出的變化:

首先,輸出顯示了process_data()函數外的print()的調用結果。

之後,data的值被列印。因為當Python解釋器將文件作為腳本執行時,變數__name__具有值"__main__",因此條件語句被計算為True。

接下來,腳本將調用process_data()並傳入data進行修改。當process_data執行時,將輸出一些狀態信息。最終,將輸出modified_data的值。

現在您可以驗證從解釋器(或其他模塊)導入best_practices.py後發生的事情了。如下示例演示了這種情況:

注意,當前結果與將條件語句添加到文件末尾之前相同。因為此時__name__變數的值為"best_practices",因此條件語句結果為False,Python將不執行process_data()。

創建名為main()的函數來包含要運行的代碼

現在,您可以編寫作為腳本由從命令行執行並導入且沒有副作用的Python代碼。接下來,您將學習如何編寫代碼並使其他程序員能輕松地理解其含義。

許多語言,如C,C++,Java以及其他的一些語言,都會定義一個叫做main()的函數,當編譯程序時,操作系統會自動調用該函數。此函數通常被稱為入口點(entry point),因為它是程序進入執行的起始位置。

相比之下,Python沒有一個特殊的函數作為腳本的入口點。實際上在Python中可以將入口點定義成任何名稱。

盡管Python不要求將函數命名為main(),但是最佳的做法是將入口點函數命名為main()。這樣方便其他程序員定位程序的起點。

此外,main()函數應該包含Python解釋器執行文件時要運行的任何代碼。這比將代碼放入條件語塊中更好,因為用戶可以在導入模塊時重復使用main()函數。

修改best_practices.py文件如下所示:

在這個示例中,定義了一個main()函數,它包含了上面的條件語句塊。之後修改條件語塊執行main()。如果您將此代碼作為腳本運行或導入,將獲得與上一節相同的輸出。

在main()中調用其他函數

另一種常見的實現方式是在main()中調用其他函數,而不是直接將代碼寫入main()。這樣做的好處在於可以實現將幾個獨立運行的子任務整合。

例如,某個腳本有如下功能:

如果在單獨的函數中各自實現這些子任務,您(或其他用戶)可以很容易地實現代碼重用。之後您可以在main()函數中創建默認的工作流。

您可以根據自己的情況選擇是否使用此方案。將任務拆分為多個函數會使重用更容易,但會增加他人理解代碼的難度。

修改best_practices.py文件如下所示:

在此示例代碼中,文件的前10行具有與之前相同的內容。第12行的第二個函數創建並返回一些示例數據,第17行的第三個函數模擬將修改後的數據寫入資料庫。

第21行定義了main()函數。在此示例中,對main()做出修改,它將調用數據讀取,數據處理以及數據寫入等功能。

首先,從read_data_from_web()中創建data。將data作為參數傳入process_data(),之後將返回modified_data。最後,將modified_data傳入write_data_to_database()。

腳本的最後兩行是條件語塊用於驗證__name__,並且如果if語句為True,則執行main()。

在命令行中運行如下所示:

根據執行結果,Python解釋器在執行main()函數時,將依次執行read_data_from_web(),process_data()以及write_data_to_database()。當然,您也可以導入best_practices.py文件並重用process_data()作為不同的數據輸入源,如下所示:

在此示例中,導入了best_practices並且將其簡寫為bp。

導入過程會導致Python解釋器執行best_practices.py的全部代碼,因此輸出顯示解釋文件用途的信息。

然後,從文件中存儲數據而不是從Web中讀取數據。之後,可以重用best_practices.py文件中的process_data()和write_data_to_database()函數。在此情況下,可以利用代碼重寫來取代在main()函數中實現全部的代碼邏輯。

實踐總結

以下是Python中main()函數的四個關鍵最佳實踐:

結論

恭喜!您現在已經了解如何創建Python main()函數了。

本文介紹了如下內容:

現在,您可以開始編寫一些非常棒的關於Python main()函數代碼啦!

Ⅱ python中定義函數的關鍵字是什麼

python中定義函數的關鍵字是def。

Python使用def關鍵字開始函數定義,緊接著是函數名,括弧內部為函數的參數,內部為函數的具體功能實現代碼,如果想要函數有返回值, 在expressions中的邏輯代碼中用return返回。

上面我們定義了一個名字為 function 的函數,函數沒有不接受參數,所以括弧內部為空,緊接著就是 函數的功能代碼。

如果執行該腳本,發現並沒有輸出任何輸出,因為我們只定義了函數,而並沒有執行函數。 這時我們在Python命令提示符中輸入函數調用 function(), 注意這里調用函數的括弧不能省略。

python的學習

如果我們用代碼實現了一個小功能,但想要在程序代碼中重復使用,不能在代碼中到處粘貼這些代碼,因為這樣做違反了軟體工程中DRY原則。 Python提供了函數功能,可以將我們這部分功能抽象成一個函數以方便程序調用,或者提供給其他模塊使用。

函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。(推薦學習:Python視頻教程)函數必須先定義,才能調用,否則會報錯,無參數時函數的調用函數名()。

有參數時函數的調,不要在定義函數的時候在函數體裡面調用本身,否則會出不來,陷入循環調用,函數需要調用函數體才會被執行,單純的只是定義函數是不會被執行的。

Ⅲ python 定義函數

python 定義函數:
在Python中,可以定義包含若干參數的函數,這里有幾種可用的形式,也可以混合使用:

1. 默認參數
最常用的一種形式是為一個或多個參數指定默認值。

>>> def ask_ok(prompt,retries=4,complaint='Yes or no Please!'):
while True:
ok=input(prompt)
if ok in ('y','ye','yes'):
return True
if ok in ('n','no','nop','nope'):
return False
retries=retries-1
if retries<0:
raise IOError('refusenik user')
print(complaint)

這個函數可以通過幾種方式調用:
只提供強制參數
>>> ask_ok('Do you really want to quit?')
Do you really want to quit?yes
True

提供一個可選參數
>>> ask_ok('OK to overwrite the file',2)
OK to overwrite the fileNo
Yes or no Please!
OK to overwrite the fileno
False

提供所有的參數
>>> ask_ok('OK to overwrite the file?',2,'Come on, only yes or no!')
OK to overwrite the file? test
Come on, only yes or no!
OK to overwrite the file?yes
True

2. 關鍵字參數
函數同樣可以使用keyword=value形式通過關鍵字參數調用

>>> def parrot(voltage,state='a stiff',action='voom',type='Norwegian Blue'):
print("--This parrot wouldn't", action, end=' ')
print("if you put",voltage,"volts through it.")
print("--Lovely plumage, the",type)
print("--It's",state,"!")

>>> parrot(1000)
--This parrot wouldn't voom if you put 1000 volts through it.
--Lovely plumage, the Norwegian Blue
--It's a stiff !
>>> parrot(action="vooooom",voltage=1000000)
--This parrot wouldn't vooooom if you put 1000000 volts through it.
--Lovely plumage, the Norwegian Blue
--It's a stiff !
>>> parrot('a thousand',state='pushing up the daisies')
--This parrot wouldn't voom if you put a thousand volts through it.
--Lovely plumage, the Norwegian Blue
--It's pushing up the daisies !

但是以下的調用方式是錯誤的:

>>> parrot(voltage=5, 'dead')
SyntaxError: non-keyword arg after keyword arg
>>> parrot()
Traceback (most recent call last):
File "<pyshell#57>", line 1, in <mole>
parrot()
TypeError: parrot() missing 1 required positional argument: 'voltage'
>>> parrot(110, voltage=220)
Traceback (most recent call last):
File "<pyshell#58>", line 1, in <mole>
parrot(110, voltage=220)
TypeError: parrot() got multiple values for argument 'voltage'
>>> parrot(actor='John')
Traceback (most recent call last):
File "<pyshell#59>", line 1, in <mole>
parrot(actor='John')
TypeError: parrot() got an unexpected keyword argument 'actor'
>>> parrot(voltage=100,action='voom',action='voooooom')
SyntaxError: keyword argument repeated

Python的函數定義中有兩種特殊的情況,即出現*,**的形式。
*用來傳遞任意個無名字參數,這些參數會以一個元組的形式訪問
**用來傳遞任意個有名字的參數,這些參數用字典來訪問
(*name必須出現在**name之前)

>>> def cheeseshop1(kind,*arguments,**keywords):
print("--Do you have any",kind,"?")
print("--I'm sorry, we're all out of",kind)
for arg in arguments:
print(arg)
print("-"*40)
keys=sorted(keywords.keys())
for kw in keys:
print(kw,":",keywords[kw])

>>> cheeseshop1("Limbuger","It's very runny, sir.","It's really very, very runny, sir.",shopkeeper="Michael Palin",client="John",sketch="Cheese Shop Sketch")
--Do you have any Limbuger ?
--I'm sorry, we're all out of Limbuger
It's very runny, sir.
It's really very, very runny, sir.
----------------------------------------
client : John
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch
>>>

3. 可變參數列表
最常用的選擇是指明一個函數可以使用任意數目的參數調用。這些參數被包裝進一個元組,在可變數目的參數前,可以有零個或多個普通的參數
通常,這些可變的參數在形參列表的最後定義,因為他們會收集傳遞給函數的所有剩下的輸入參數。任何出現在*args參數之後的形參只能是「關鍵字參數」
>>> def contact(*args,sep='/'):
return sep.join(args)

>>> contact("earth","mars","venus")
'earth/mars/venus'

4. 拆分參數列表
當參數是一個列表或元組,但函數需要分開的位置參數時,就需要拆分參數
調用函數時使用*操作符將參數從列表或元組中拆分出來
>>> list(range(3,6))
[3, 4, 5]
>>> args=[3,6]
>>> list(range(*args))
[3, 4, 5]
>>>

以此類推,字典可以使用**操作符拆分成關鍵字參數

>>> def parrot(voltage,state='a stiff',action='voom'):
print("--This parrot wouldn't", action,end=' ')
print("if you put",voltage,"volts through it.",end=' ')
print("E's", state,"!")

>>> d={"voltage":"four million","state":"bleedin' demised","action":"VOOM"}
>>> parrot(**d)
--This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

5. Lambda
在Python中使用lambda來創建匿名函數,而用def創建的是有名稱的。
python lambda會創建一個函數對象,但不會把這個函數對象賦給一個標識符,而def則會把函數對象賦值給一個變數
python lambda它只是一個表達式,而def則是一個語句

>>> def make_incrementor(n):
return lambda x:x+n

>>> f=make_incrementor(42)
>>> f(0)
42
>>> f(2)
44

>>> g=lambda x:x*2
>>> print(g(3))
6
>>> m=lambda x,y,z:(x-y)*z
>>> print(m(3,1,2))
4

6. 文檔字元串
關於文檔字元串內容和格式的約定:
第一行應該總是關於對象用途的摘要,以大寫字母開頭,並且以句號結束
如果文檔字元串包含多行,第二行應該是空行

>>> def my_function():
"""Do nothing, but document it.

No, really, it doesn't do anything.
"""
pass

>>> print(my_function.__doc__)
Do nothing, but document it.

No, really, it doesn't do anything.

Ⅳ python中定義函數的關鍵字

函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。

函數能提高應用的模塊性,和代碼的重復利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。

定義一個函數

可以定義一個由自己想要功能的函數,以下是簡單的規則:

1.函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括弧()。

2.任何傳入參數和自變數必須放在圓括弧中間。圓括弧之間可以用於定義參數。

3.函數的第一行語句可以選擇性地使用文檔字元串—用於存放函數說明。

4.函數內容以冒號起始,並且縮進。

5.return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。

語法

Python 定義函數使用 def 關鍵字,一般格式如下:

1

2

def 函數名(參數列表):

函數體

默認情況下,參數值和參數名稱是按函數聲明中定義的順序匹配起來的。

示例

讓我們使用函數來輸出"Hello World!":

1

2

>>>def hello() :

print("Hello World!")

輸出結果

>>> hello()

Hello World!

Ⅳ Python中定義函數的使用方法

4.6. 定義函數
我們可以創建一個用來生成指定邊界的斐波那契數列的函數:
>>> def fib(n): # write Fibonacci series up to n
... """Print a Fibonacci series up to n."""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
關鍵字 def 引入了一個函數 定義。在其後必須跟有函數名和包括形式參數的圓括弧。函數體語句從下一行開始,必須是縮進的。
函數體的第一行語句可以是可選的字元串文本,這個字元串是函數的文檔字元串,或者稱為 docstring。(更多關於 docstrings 的信息請參考 文檔字元串) 有些工具通過 docstrings 自動生成在線的或可列印的文檔,或者讓用戶通過代碼交互瀏覽;在你的代碼中包含 docstrings 是一個好的實踐,讓它成為習慣吧。
函數 調用 會為函數局部變數生成一個新的符號表。確切的說,所有函數中的變數賦值都是將值存儲在局部符號表。變數引用首先在局部符號表中查找,然後是包含函數的局部符號表,然後是全局符號表,最後是內置名字表。因此,全局變數不能在函數中直接賦值(除非用 global 語句命名),盡管他們可以被引用。
函數引用的實際參數在函數調用時引入局部符號表,因此,實參總是 傳值調用 (這里的 值 總是一個對象 引用 ,而不是該對象的值)。[1] 一個函數被另一個函數調用時,一個新的局部符號表在調用過程中被創建。
一個函數定義會在當前符號表內引入函數名。函數名指代的值(即函數體)有一個被 Python 解釋器認定為 用戶自定義函數 的類型。 這個值可以賦予其他的名字(即變數名),然後它也可以被當作函數使用。這可以作為通用的重命名機制:
>>> fib
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89
如果你使用過其他語言,你可能會反對說:fib 不是一個函數,而是一個方法,因為它並不返回任何值。事實上,沒有 return 語句的函數確實會返回一個值,雖然是一個相當令人厭煩的值(指 None )。這個值被稱為 None (這是一個內建名稱)。如果 None 值是唯一被書寫的值,那麼在寫的時候通常會被解釋器忽略(即不輸出任何內容)。如果你確實想看到這個值的輸出內容,請使用 print() 函數:

閱讀全文

與python動態創建函數相關的資料

熱點內容
批處理編譯VS代碼 瀏覽:889
uchar哪個編譯器 瀏覽:27
initializejava 瀏覽:707
單片機的系統組成 瀏覽:610
中國天河二號演算法 瀏覽:647
程序員是怎麼瘋的 瀏覽:598
程序員的貓有幾條命 瀏覽:832
安卓如何把圖片傳到電腦上 瀏覽:895
到去哪兒旅行app怎麼買票 瀏覽:444
工商銀行app房貸還款在哪裡看 瀏覽:761
最新民生通訊app從哪裡下載 瀏覽:378
如何在發簡訊時給自己手機號加密 瀏覽:773
擴展單片機ram定址方式是什麼 瀏覽:318
phpide是什麼 瀏覽:752
單片機相關軟體 瀏覽:818
eclipse如何編譯c11 瀏覽:286
加密游戲app 瀏覽:73
vs2010編譯嵌套太深 瀏覽:982
程序員面試注意事項 瀏覽:742
scratch編譯為h5 瀏覽:210