Python 中的前向宣告
本文將討論我們是否可以在 Python 中實現前向宣告。我們還將研究在 Python 中模擬前向宣告的不同方法。
前向宣告
前向宣告是在實現函式、類或變數用法之前宣告函式、類或變數的簽名。
在 C++ 中,前向宣告用於定義函式的簽名,如下所示。
#include <iostream>
using namespace std;
int myFun(int,int);
int main()
{
cout<<myFun(5,10);
return 0;
}
int myFun(int a, int b){
int s= a+b;
return s;
}
在上面的示例中,我們使用前向宣告來使用語句 int myFun(int,int);
定義函式 myFun
簽名。在此宣告之後,編譯器知道原始碼檔案中存在一個名為 myFun
的函式。
因此,即使該函式在其定義之前被呼叫,程式也不會出現任何錯誤並且會成功執行。
在 Python 中,我們不使用前向宣告。但是,在編寫 Python 程式的原始碼時,使用前向宣告可以帶來各種好處。
為什麼我們需要 Python 中的前向宣告
雖然 Python 沒有前向宣告的語法規範,但在很多情況下我們需要前向宣告。
如果函式 Fun1
在實現 Fun2
之前使用 Fun2
,則檢視程式碼的人可能不知道 Fun2
的簽名、輸入或輸出。我們可以通過使用前向宣告來通知程式碼審查者關於 Fun2
的簽名來避免這種情況。
-
有時,我們可能會將使用者定義類的物件傳遞給函式。同樣,如果類沒有在函式之前實現,我們將需要顯式地顯示類的屬性。
如果我們在 Python 中使用前向宣告,就可以避免這種情況。
-
與作為引數傳遞類似,如果使用者定義的類是另一個類的屬性,那麼瞭解給定的類物件的行為對於理解程式碼至關重要。通過 Python 中的前向宣告,我們可以告知類物件的行為。
-
有時,我們可能需要告知程式碼審查者變數的資料型別。在這種情況下,我們可以使用前向宣告來定義變數的屬性。
Python 中變數的前向宣告
我們可以使用前向宣告來使用型別提示和型別模組來宣告變數。讓我們一一討論它們。
在 Python 中使用型別提示進行前向宣告
型別提示允許我們定義變數的型別。
語法:
var: type
這裡,
var
是變數名。type
是變數的資料型別。
你可以使用型別提示來轉發宣告 Python,如下所示。
myStr: str
myNumber: int
在上面的例子中,變數 myStr
和 myNumber
在宣告之前是不存在的。因此,在使用型別提示的前向宣告之後使用 myStr
或 myNumber
將導致 NameError
異常,如下所示。
myStr: str
myNumber: int
print(myStr)
print(myNumber)
輸出:
Traceback (most recent call last):
File "/home/aditya1117/pythonProject/string12.py", line 3, in <module>
print(myStr)
NameError: name 'myStr' is not defined
在這裡,變數 myStr
和 myNumber
存在。然而,它們還沒有被分配一個值。
因此,它們既沒有分配記憶體,也沒有出現在程式的符號表中。因此,當我們使用變數而不給它們賦值時,就會發生 NameError
異常。
要使用該變數,你必須首先為其分配一個值。
myStr: str
myNumber: int
myStr = "Delft-stack"
myNumber = 123
print(myStr)
print(myNumber)
輸出:
Delft-stack
123
一旦我們為變數賦值,它們就會被分配記憶體並被新增到符號表中。因此,程式不會出錯併成功執行。
在這裡,你可以說使用型別提示的變數前向宣告與註釋一樣好。
在 Python 中使用型別模組的前向宣告
使用型別提示定義使用者定義類的物件需要在變數宣告之前實現。否則,程式將遇到 NameError
異常。
你可以在以下示例中觀察到這一點。
myStr: str
myNumber: int
myObject: myClass
輸出:
Traceback (most recent call last):
File "/home/aditya1117/pythonProject/string12.py", line 3, in <module>
myObject: myClass
NameError: name 'myClass' is not defined
這裡沒有定義字面量 myClass
。因此,程式會遇到 NameError
異常。
為了避免這樣的錯誤,我們首先需要定義 myClass
是一個類名。我們可以使用 typing
模組中定義的 NewType()
函式。
NewType()
函式將表示類名的字串作為其第一個輸入引數。它將新類的父類作為第二個引數。
執行後,它返回一個新函式,我們可以將其分配給新類的類名。之後,我們可以像在型別提示中使用 int、float 和 double 這樣的文字一樣使用新的類名。
為了定義一個 myClass
型別的類,我們將傳遞字面量 myClass
作為第一個輸入引數,並將 None
物件作為第二個引數。執行完 NewType()
函式後,我們可以在型別提示中使用 myClass
進行前向宣告,如下所示。
import typing
myClass = typing.NewType("myClass", None)
myStr: str
myNumber: int
myObject: myClass
程式不會遇到 NameError
異常,因為我們已經宣告 myClass
是一個物件型別。
在 Python 中前向宣告一個函式
在 Python 中,你應該始終在使用它之前定義一個函式。你可以在另一個函式 fun2
的定義中使用函式 fun1
。
但是,你需要確保在定義 fun1
之前不會呼叫 fun2
。否則,程式將遇到 NameError
異常。
fun1()
def fun1():
print("I am in fun1")
輸出:
Traceback (most recent call last):
File "/home/aditya1117/string12.py", line 1, in <module>
fun1()
NameError: name 'fun1' is not defined
Process finished with exit code 1
在這裡,我們在定義之前的 main()
函式中使用了函式 fun1()
。由於這個原因,程式遇到了一個 NameError
異常,表明名稱 fun1
沒有定義。
僅在定義後使用 fun1
可以避免 NameError
異常,如下所示。
def fun1():
print("I am in fun1")
fun1()
輸出:
I am in fun1
まとめ
本文討論瞭如何在 Python 中模擬前向宣告。前向宣告僅在使用型別提示來宣告使用者定義型別的變數時才有意義。
此外,僅在對變數強制執行資料型別時才需要型別提示。因此,僅在對變數實施型別約束時才使用前向宣告。
否則,你的程式將無緣無故地做額外的工作。最好總是在 Python 中使用它之前定義一個函式。