簡體   English   中英

Python解釋器如何在動態類型中工作?

[英]How does Python interpreter work in dynamic typing?

我讀了這個問題,但它沒有給我一個明確的答案: Python解釋器如何尋找類型?

python解釋器如何知道變量的類型? 我不知道如何獲得類型。 我在這里看看幕后發生了什么。 在下面的示例中,它如何將類int或string與我的變量相關聯。

它是如何知道這是一個int:

>>> i = 123
>>> type(i) 
<class 'int'>

或那個字符串:

>>> i = "123"
>>> type(i)
<class 'str'>

它如何將類int或string與我的變量相關聯

Python沒有。 變量沒有類型 只有變量引用的對象具有類型。 變量只是指向對象的名稱

例如,以下內容還顯示了對象的類型,但不涉及任何變量

>>> type(1)
<class 'int'>
>>> type('foobar')
<class 'str'>

當使用type(variable) ,則variable表達式的一部分簡單地返回名稱引用的對象,傳遞到物體type()函數。 當使用1'foobar' ,表達式是生成對象的文字,然后傳遞給type()函數。

Python對象只是解釋器內存中的數據結構; 在CPython C結構中使用。 變量只是那些結構的引用(指針)。 CPython中的基本類型結構稱為PyObject ,這個結構有一個ob_type ,告訴Python什么類型的東西。 類型只是更多的C結構

如果你想跟隨CPython源代碼,你可以從bltinmodule.c源碼開始(因為type是內置名稱),它將type定義為PyType_Type結構 調用類型type也是類型 )調用它們的tp_new函數PyType_Type 將其定義type_new函數 此函數使用一個參數處理調用,如下所示:

/* Special case: type(x) should return x->ob_type */
{
    const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
    const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);

    if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
        PyObject *x = PyTuple_GET_ITEM(args, 0);
        Py_INCREF(Py_TYPE(x));
        return (PyObject *) Py_TYPE(x);
    }

這里x是你傳入的PyObject對象; 注意,不是變量,而是對象! 因此,對於1整數對象或'foobar'字符串對象,將返回Py_TYPE()宏結果。 Py_TYPE是一個宏ob_type返回任何PyObject結構的ob_type值。

所以現在你有1'foobar'的類型對象; 你怎么在解釋器會話中看到<class 'int'><class 'str'> Python交互式解釋器自動在任何表達式結果上使用repr()函數 在C結構PyType_Type定義中PyType_Type結構被結合,因此所有用於該類型的時隙是直接可用; 我會在這里省略究竟是如何工作 對於類型對象,使用repr()表示調用type_repr函數 ,該函數返回:

rtn = PyUnicode_FromFormat("<class '%s'>", type->tp_name);

所以最后, type(1)得到->ob_type槽,(事實證明它是Python 3中的PyLong_Type結構 ,長篇故事),並且該結構的tp_name槽設置為"int"

TL; DR :Python變量沒有類型,它們只是指向對象的指針。 對象具有類型,如果您在解釋器中回顯對象,Python解釋器將遵循一系列間接引用來到達要打印的類型名稱。

通過使用特定類的對象來“實現”變量的“類型”概念。

所以

a=float()

類型的對象float ,如由類定義float通過返回float() Python知道它是什么類型,因為對象是如何工作的:你知道它們是什么類型。 a現在是一個float對象,值為0.0。

對於內置,它是相同的,只是他們有簡短的聲明它們。

i=123

是相同的

i=int(123)

int()返回類integer的對象,值為123。

同樣

i="123"

是相同的

i=str("123")

str("123")返回str類的對象,值為“123”

Python變量沒有類型,它們只是對象的引用。 無論引用什么,引用的大小都是相同的。 在C Python實現它是一個指針,並確實有一個類型,它的指針到一個Python對象: PyObject * 無論對象類如何,指針都是相同的類型。 另一方面,對象知道它們屬於哪個類。

有人認為Python沒有變量,只有名稱,盡管對大多數人來說這是一個太過分的步驟。

CPython實現中的引用具有id(標識符),其實際上是虛擬地址。 這個地址的細節和價值不值得追求 - 它可以(並且可能會)在不同版本之間進行更改,並不意味着用於識別對象的唯一編號以外的任何其他內容。 然而,它可以提供有趣的指針(原諒雙關語)發生的事情:

>>> x = 42
>>> y = x
>>> id(x)
4297539264
>>> id(y)
4297539264

注意xy的id(地址)是相同的 - 它們引用同一個對象,一個值為42的int 。那么,當我們改變x時會發生什么, y也會改變嗎?

>>> x = "hello"
>>> id(x)
4324832176
>>> id(y)
4297539264

謝天謝地。 現在x只是引用類str的新對象,其值為“Hello”。

什么時候我們:

>>> id(y)
4297539264
>>> y = 37
>>> id(y)
4297539104 

y的id改變了! 這是因為它現在引用了一個不同的對象。 int不可變的 ,因此賦值y = 37沒有改變原始對象(42)它創建了一個新對象。 值為42的對象的引用計數遞減,現在(理論上)可以刪除。 在實踐中,出於效率原因,它可能會留在內存中,但這是一個實現細節。

然而:

>>> a = [1,2,3,4]
>>> b = a
>>> id(a)
4324804808
>>> id(b)
4324804808
>>> a[0] = 99
>>> b
[99, 2, 3, 4]

所以更改列表a 已經改變了b 這是因為列表是可變的 ,它們可以改變。 賦值b = a只復制引用,而不是列表。 請參閱標准庫中的copy

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM