自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深度解密 Python 的浮點數(shù)是怎么實現(xiàn)的?

開發(fā) 前端
假設(shè)我們要將兩個浮點數(shù)相加,相信你已經(jīng)知道解釋器會如何做了?通過 PyFloat_AsDouble 將兩個浮點數(shù)的 ob_fval 抽出來,然后相加,最后再根據(jù)相加的結(jié)果創(chuàng)建一個新的 PyFloatObject 即可。

楔子

從現(xiàn)在開始,我們就來分析 Python 的內(nèi)置對象,看看它們在底層是如何實現(xiàn)的。但說實話,我們在前面幾篇文章中介紹對象的時候,已經(jīng)說了不少了,不過從現(xiàn)在開始要進行更深入的分析。

除了對象本身,還要看對象支持的操作在底層是如何實現(xiàn)的。我們首先以浮點數(shù)為例,因為它是最簡單的,沒錯,浮點數(shù)比整數(shù)要簡單,至于為什么,等我們分析整數(shù)的時候就知道了。

浮點數(shù)的底層結(jié)構(gòu)

要想搞懂浮點數(shù)的實現(xiàn)原理,就要知道它在底層是怎么定義的,當然在這之前我們已經(jīng)見過它很多遍了。

// Include/cpython/floatobject.h
typedef struct {
    PyObject_HEAD
    double ob_fval;
} PyFloatObject;

它包含了一個公共頭部 PyObject 和一個 double 類型的 ob_fval 字段,毫無疑問這個 ob_fval 字段負責存儲浮點數(shù)的具體數(shù)值。

我們以 e = 2.71 為例,底層結(jié)構(gòu)如下。

圖片圖片

還是很簡單的,每個對象在底層都是由結(jié)構(gòu)體表示的,這些結(jié)構(gòu)體中有的字段負責維護對象的元信息,有的字段負責維護具體的值。比如這里的  2.71,總要有一個字段來存儲 2.71 這個值,而這個字段就是 ob_fval。所以浮點數(shù)的結(jié)構(gòu)非常簡單,直接使用一個 C 的 double 來維護。

假設(shè)我們要將兩個浮點數(shù)相加,相信你已經(jīng)知道解釋器會如何做了?通過 PyFloat_AsDouble 將兩個浮點數(shù)的 ob_fval 抽出來,然后相加,最后再根據(jù)相加的結(jié)果創(chuàng)建一個新的 PyFloatObject 即可。

浮點數(shù)是怎么創(chuàng)建的

下面來看看浮點數(shù)是如何創(chuàng)建的,在前面的文章中,我們說對象可以使用對應(yīng)的特定類型 API 創(chuàng)建,也可以通過調(diào)用類型對象創(chuàng)建。

調(diào)用類型對象 float 創(chuàng)建實例對象,解釋器會執(zhí)行元類 type 的 tp_call,它指向了 type_call 函數(shù)。然后 type_call 內(nèi)部會先調(diào)用類型對象(這里是 float)的 tp_new 為其實例對象申請一份空間,申請完畢之后對象就已經(jīng)創(chuàng)建好了。然后再調(diào)用 tp_init,并將實例對象作為參數(shù)傳遞進去,進行初始化,也就是設(shè)置屬性。

但是對于 float 來說,它內(nèi)部的 tp_init 字段為 0,也就是空。

圖片圖片

這就說明 float 沒有 __init__,因為浮點數(shù)太過簡單,只需要一個 tp_new 即可。我們舉個例子:

class Girl1:

    def __init__(self, name, age):
        self.name = name
        self.age = age

# __new__  負責開辟空間、生成實例對象
# __init__ 負責給實例對象綁定屬性

# 但其實 __init__ 所做的工作可以直接在 __new__ 當中完成
# 換言之有 __new__ 就足夠了,其實可以沒有 __init__
# 我們將上面的例子改寫一下
class Girl2:

    def __new__(cls, name, age):
        instance = object.__new__(cls)
        instance.name = name
        instance.age = age
        return instance

g1 = Girl1("古明地覺", 16)
g2 = Girl2("古明地覺", 16)
print(g1.__dict__ == g2.__dict__)  # True

我們看到效果是等價的,因為 __init__ 負責給 self 綁定屬性,而這個 self 是 __new__ 返回的。那么很明顯,我們也可以在 __new__ 當中綁定屬性,而不需要 __init__。

責任編輯:武曉燕 來源: 古明地覺的編程教室
相關(guān)推薦

2020-09-15 12:57:46

C 語言浮點數(shù)內(nèi)存

2023-07-05 08:00:58

Redis數(shù)據(jù)庫

2018-08-24 10:16:23

內(nèi)存浮點數(shù)存儲

2017-10-16 10:42:27

前端JavaScript浮點數(shù)

2011-05-25 14:10:38

浮點數(shù)

2020-10-12 06:38:08

存儲定點數(shù)

2010-07-22 17:39:44

2015-12-02 10:21:34

JavaScript浮點數(shù)精度調(diào)整

2010-01-15 15:21:35

C++

2021-10-19 14:04:28

C++類型數(shù)字

2009-05-19 10:10:01

Oracle時間加減時間操作

2024-07-11 15:50:36

2021-11-15 09:32:06

浮點面試Java

2022-06-15 15:44:21

無損數(shù)據(jù)壓縮鴻蒙

2024-08-23 08:43:08

2025-04-01 07:50:00

Dinero.js前端開發(fā)

2022-09-16 07:24:12

Python 的四舍

2024-09-18 13:49:42

2024-08-02 11:33:49

2024-09-05 10:49:42

點贊
收藏

51CTO技術(shù)棧公眾號