欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入理解Python虛擬機(jī)中復(fù)數(shù)(complex)的實(shí)現(xiàn)原理及源碼剖析

 更新時(shí)間:2023年03月14日 09:11:16   作者:一無(wú)是處的研究僧  
在本篇文章當(dāng)中主要給大家介紹在 cpython 虛擬機(jī)當(dāng)中是如何實(shí)現(xiàn) 復(fù)數(shù) complex 這個(gè)數(shù)據(jù)類型的,這個(gè)數(shù)據(jù)類型在 cpython 當(dāng)中一應(yīng)該是一個(gè)算比較簡(jiǎn)單的數(shù)據(jù)類型了,非常容易理解

復(fù)數(shù)數(shù)據(jù)結(jié)構(gòu)

在 cpython 當(dāng)中對(duì)于復(fù)數(shù)的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)如下所示:

typedef struct {
    double real;
    double imag;
} Py_complex;
#define PyObject_HEAD                   PyObject ob_base;
typedef struct {
    PyObject_HEAD
    Py_complex cval;
} PyComplexObject;
typedef struct _object {
    _PyObject_HEAD_EXTRA
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

上面的數(shù)據(jù)結(jié)構(gòu)圖示如下:

復(fù)數(shù)的數(shù)據(jù)在整個(gè) cpython 虛擬機(jī)當(dāng)中來(lái)說(shuō)應(yīng)該算是比較簡(jiǎn)單的了,除了一個(gè) PyObject 頭部之外就是實(shí)部和虛部了。

  • ob_refcnt,表示對(duì)象的引用記數(shù)的個(gè)數(shù),這個(gè)對(duì)于垃圾回收很有用處,后面我們分析虛擬機(jī)中垃圾回收部分在深入分析。
  • ob_type,表示這個(gè)對(duì)象的數(shù)據(jù)類型是什么,在 python 當(dāng)中有時(shí)候需要對(duì)數(shù)據(jù)的數(shù)據(jù)類型進(jìn)行判斷比如 isinstance, type 這兩個(gè)關(guān)鍵字就會(huì)使用到這個(gè)字段。
  • real,表示復(fù)數(shù)的實(shí)部。
  • imag,表示復(fù)數(shù)的虛部。

復(fù)數(shù)的操作

復(fù)數(shù)加法

下面是 cpython 當(dāng)中對(duì)于復(fù)數(shù)加法的實(shí)現(xiàn),為了簡(jiǎn)潔刪除了部分無(wú)用代碼。

static PyObject *
complex_add(PyObject *v, PyObject *w)
{
    Py_complex result;
    Py_complex a, b;
    TO_COMPLEX(v, a); // TO_COMPLEX 這個(gè)宏的作用就是將一個(gè) PyComplexObject 中的 Py_complex 對(duì)象存儲(chǔ)到 a 當(dāng)中
    TO_COMPLEX(w, b);
    result = _Py_c_sum(a, b); // 這個(gè)函數(shù)的具體實(shí)現(xiàn)在下方
    return PyComplex_FromCComplex(result); // 這個(gè)函數(shù)的具體實(shí)現(xiàn)在下方
}
 
// 真正實(shí)現(xiàn)復(fù)數(shù)加法的函數(shù)
Py_complex
_Py_c_sum(Py_complex a, Py_complex b)
{
    Py_complex r;
    r.real = a.real + b.real;
    r.imag = a.imag + b.imag;
    return r;
}
 
PyObject *
PyComplex_FromCComplex(Py_complex cval)
{
    PyComplexObject *op;
 
    /* Inline PyObject_New */
    // 申請(qǐng)內(nèi)存空間
    op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
    if (op == NULL)
        return PyErr_NoMemory();
    // 將這個(gè)對(duì)象的引用計(jì)數(shù)設(shè)置成 1
    (void)PyObject_INIT(op, &PyComplex_Type);
    // 將復(fù)數(shù)結(jié)構(gòu)體保存下來(lái)
    op->cval = cval;
    return (PyObject *) op;
}

上面代碼的整體過(guò)程比較簡(jiǎn)單:

  • 首先先從 PyComplexObject 提取真正的復(fù)數(shù)部分。
  • 將提取到的兩個(gè)復(fù)數(shù)進(jìn)行相加操作。
  • 根據(jù)得到的結(jié)果在創(chuàng)建一個(gè) PyComplexObject 對(duì)象,并且將這個(gè)對(duì)象返回。

復(fù)數(shù)取反

復(fù)數(shù)取反操作就是將實(shí)部和虛部取相反數(shù)就可以了,這個(gè)操作也比較簡(jiǎn)單。

static PyObject *
complex_neg(PyComplexObject *v)
{
    Py_complex neg;
    neg.real = -v->cval.real;
    neg.imag = -v->cval.imag;
    return PyComplex_FromCComplex(neg);
}
 
PyObject *
PyComplex_FromCComplex(Py_complex cval)
{
    PyComplexObject *op;
 
    /* Inline PyObject_New */
    op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
    if (op == NULL)
        return PyErr_NoMemory();
    (void)PyObject_INIT(op, &PyComplex_Type);
    op->cval = cval;
    return (PyObject *) op;
}

Repr 函數(shù)

我們現(xiàn)在來(lái)介紹一下一個(gè)有趣的方法,就是復(fù)數(shù)類型的 repr 函數(shù),這個(gè)和類的 __repr__ 函數(shù)是作用是一樣的我們看一下復(fù)數(shù)的輸出是什么:

>>> data = complex(0, 1)
>>> data
1j
>>> data = complex(1, 1)
>>> data
(1+1j)
>>> print(data)
(1+1j)

復(fù)數(shù)的 repr 對(duì)應(yīng)的 C 函數(shù)如下所示:

static PyObject *
complex_repr(PyComplexObject *v)
{
    int precision = 0;
    char format_code = 'r';
    PyObject *result = NULL;
 
    /* If these are non-NULL, they'll need to be freed. */
    char *pre = NULL;
    char *im = NULL;
 
    /* These do not need to be freed. re is either an alias
       for pre or a pointer to a constant.  lead and tail
       are pointers to constants. */
    char *re = NULL;
    char *lead = "";
    char *tail = "";
    // 對(duì)應(yīng)實(shí)部等于 0 虛部大于 0 的情況
    if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) {
        /* Real part is +0: just output the imaginary part and do not
           include parens. */
        re = "";
        im = PyOS_double_to_string(v->cval.imag, format_code,
                                   precision, 0, NULL);
        if (!im) {
            PyErr_NoMemory();
            goto done;
        }
    } else {
        /* Format imaginary part with sign, real part without. Include
           parens in the result. */
        // 將實(shí)部浮點(diǎn)數(shù)變成字符串
        pre = PyOS_double_to_string(v->cval.real, format_code,
                                    precision, 0, NULL);
        if (!pre) {
            PyErr_NoMemory();
            goto done;
        }
        re = pre;
        // 將虛部浮點(diǎn)數(shù)變成字符串
        im = PyOS_double_to_string(v->cval.imag, format_code,
                                   precision, Py_DTSF_SIGN, NULL);
        if (!im) {
            PyErr_NoMemory();
            goto done;
        }
        // 用什么括號(hào)包圍起來(lái)
        lead = "(";
        tail = ")";
    }
    result = PyUnicode_FromFormat("%s%s%sj%s", lead, re, im, tail);
  done:
    PyMem_Free(im);
    PyMem_Free(pre);
 
    return result;
}

我們現(xiàn)在修改源程序?qū)⑸厦娴?() 兩個(gè)括號(hào)變成 [],編譯之后執(zhí)行的結(jié)果如下所示:

可以看到括號(hào)變成了 [] 。

總結(jié)

在本篇文章當(dāng)中主要給大家介紹了在 cpython 虛擬機(jī)當(dāng)中對(duì)于復(fù)數(shù)這一類型的數(shù)據(jù)結(jié)構(gòu)以及他的具體實(shí)現(xiàn)??傮w來(lái)說(shuō)這個(gè)數(shù)據(jù)結(jié)構(gòu)比較簡(jiǎn)單,操作也相對(duì)容易,比較容易理解,最后簡(jiǎn)單介紹了一下復(fù)數(shù)類型的 repr 實(shí)現(xiàn),其實(shí)這個(gè)函數(shù)和 python 的類型系統(tǒng)有關(guān),目前我們還沒(méi)有仔細(xì)去討論這一點(diǎn),在后續(xù)的文章當(dāng)中我們將深入的去學(xué)習(xí)這個(gè)知識(shí)點(diǎn),現(xiàn)在我們就先了解其中部分函數(shù)即可。

到此這篇關(guān)于深入理解Python虛擬機(jī)中復(fù)數(shù)(complex)的實(shí)現(xiàn)原理及源碼剖析的文章就介紹到這了,更多相關(guān)Python虛擬機(jī) 復(fù)數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python語(yǔ)法分析之字符串格式化

    Python語(yǔ)法分析之字符串格式化

    這篇文章主要給大家介紹了關(guān)于Python語(yǔ)法分析之字符串格式化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • python命令 -u參數(shù)用法解析

    python命令 -u參數(shù)用法解析

    這篇文章主要介紹了python命令 -u參數(shù)用法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • python中使用you-get庫(kù)批量在線下載bilibili視頻的教程

    python中使用you-get庫(kù)批量在線下載bilibili視頻的教程

    這篇文章主要介紹了使用python中you-get庫(kù)批量在線下載bilibili視頻的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 基于PyTorch的permute和reshape/view的區(qū)別介紹

    基于PyTorch的permute和reshape/view的區(qū)別介紹

    這篇文章主要介紹了基于PyTorch的permute和reshape/view的區(qū)別介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-06-06
  • 讓python 3支持mysqldb的解決方法

    讓python 3支持mysqldb的解決方法

    這篇文章主要介紹了關(guān)于讓python 3支持mysqldb的解決方法,文中給出解決的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,有需要的朋友可以一起來(lái)看看。
    2017-02-02
  • linux環(huán)境打包python工程為可執(zhí)行程序的過(guò)程

    linux環(huán)境打包python工程為可執(zhí)行程序的過(guò)程

    本次需求,在ubuntu上面開(kāi)發(fā)的python代碼程序需要打包成一個(gè)可執(zhí)行程序然后交付給甲方,因?yàn)椴荒苤苯咏o源碼給甲方,所以尋找方法將python開(kāi)發(fā)的源碼打包成一個(gè)可執(zhí)行程序,本次在ubuntu上打包python源碼的方法和在window上打包的有點(diǎn)類似,感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • 淺談Python type的使用

    淺談Python type的使用

    今天小編就為大家分享一篇淺談Python type的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • python 實(shí)現(xiàn)多線程下載m3u8格式視頻并使用fmmpeg合并

    python 實(shí)現(xiàn)多線程下載m3u8格式視頻并使用fmmpeg合并

    這篇文章主要介紹了python 實(shí)現(xiàn)多線程下載m3u8格式視頻,使用fmmpeg合并的實(shí)例代碼,需要的朋友可以參考下
    2019-11-11
  • Python輸出列表(list)的倒序/逆序的幾種方法

    Python輸出列表(list)的倒序/逆序的幾種方法

    列表是一個(gè)有序的元素集合,而列表的倒序或逆序操作也是常見(jiàn)的需求之一,本文主要介紹了Python輸出列表(list)的倒序/逆序的幾種方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • pyodps中的apply用法及groupby取分組排序第一條數(shù)據(jù)

    pyodps中的apply用法及groupby取分組排序第一條數(shù)據(jù)

    這篇文章主要介紹了pyodps中的apply用法及groupby取分組排序第一條數(shù)據(jù),問(wèn)綻放圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值需要的小伙伴可以參考一下
    2022-05-05

最新評(píng)論