精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python 函數在底層長什么樣子?

開發 前端
Python 一切皆對象,函數也不例外,函數這種抽象機制在底層是通過 PyFunctionObject 結構體實現的。

楔子

函數是任何一門編程語言都具備的基本元素,它可以將多個動作組合起來,一個函數代表了一系列的動作。而且在調用函數時會干什么來著,沒錯,要創建棧幀,用于函數的執行。

那么下面就來看看函數在 C 中是如何實現的,生得一副什么模樣。

PyFunctionObject

Python 一切皆對象,函數也不例外,函數這種抽象機制在底層是通過 PyFunctionObject 結構體實現的。

// Include/cpython/funcobject.h
#define COMMON_FIELDS(PREFIX) \
    PyObject *PREFIX ## globals; \
    PyObject *PREFIX ## builtins; \
    PyObject *PREFIX ## name; \
    PyObject *PREFIX ## qualname; \
    PyObject *PREFIX ## code; \
    PyObject *PREFIX ## defaults; \
    PyObject *PREFIX ## kwdefaults; \
    PyObject *PREFIX ## closure;

typedef struct {
    PyObject_HEAD
    COMMON_FIELDS(func_)
    PyObject *func_doc;         
    PyObject *func_dict;        
    PyObject *func_weakreflist; 
    PyObject *func_module;      
    PyObject *func_annotations; 
    PyObject *func_typeparams;  
    vectorcallfunc vectorcall;
    uint32_t func_version;
} PyFunctionObject;

如果將宏展開的話,結構體就是下面這個樣子。

typedef struct {
    PyObject_HEAD
    PyObject *func_globals; 
    PyObject *func_builtins; 
    PyObject *func_name; 
    PyObject *func_qualname; 
    PyObject *func_code; 
    PyObject *func_defaults; 
    PyObject *func_kwdefaults; 
    PyObject *func_closure;
    PyObject *func_doc;         
    PyObject *func_dict;        
    PyObject *func_weakreflist; 
    PyObject *func_module;      
    PyObject *func_annotations; 
    PyObject *func_typeparams;  
    vectorcallfunc vectorcall;
    uint32_t func_version;
} PyFunctionObject;

我們來解釋一下這些字段,并實際獲取一下,看看它們在 Python 中是如何表現的。

func_globals:global 名字空間

def foo(a, b, c):
    pass

name = "古明地覺"
print(foo.__globals__)  # {..., 'name': '古明地覺'}
# 拿到的其實就是外部的 global名字空間
print(foo.__globals__ is globals())  # True

函數內部之所以可以訪問全局變量,就是因為它保存了全局名字空間。

func_builtins:builtin 名字空間

def foo(a, b, c):
    pass

print(foo.__builtins__ is __builtins__.__dict__)  # True

注意:在之前的版本中,函數內部是沒有這個字段的。

func_name:函數的名字

def foo(name, age):
    pass

print(foo.__name__)  # foo

當然不光是函數,方法、類、模塊都有自己的名字。

import numpy as np

print(np.__name__)  # numpy
print(np.ndarray.__name__)  # ndarray
print(np.array([1, 2, 3]).transpose.__name__)  # transpose

除了 func_name 之外,函數還有一個 func_qualname 字段。

func_qualname:函數的全限定名

print(str.join.__name__)  # join
print(str.join.__qualname__)  # str.join

函數如果定義在類里面,那么它就叫類的成員函數,但它本質上依舊是個函數,和普通函數并無區別。只是在獲取全限定名的時候,會帶上類名。

func_code:函數對應的 PyCodeObject 對象

def foo(a, b, c):
    pass

code = foo.__code__
print(code)  # <code object foo at ......>
print(code.co_varnames)  # ('a', 'b', 'c')

函數便是基于 PyCodeObject 構建的。

func_defaults:函數參數的默認值

def foo(name="古明地覺", age=16):
    pass
# 打印的是默認值
print(foo.__defaults__)  # ('古明地覺', 16)

def bar():
    pass
# 沒有默認值的話,__defaults__ 為 None
print(bar.__defaults__)  # None

注:默認值只會創建一次,所以默認值不應該是可變對象。

func_kwdefaults:只能通過關鍵字參數傳遞的 "參數" 和 "該參數的默認值" 組成的字典

def foo(name="古明地覺", age=16):
    pass
# 打印為 None,這是因為雖然有默認值
# 但并不要求必須通過關鍵字參數的方式傳遞
print(foo.__kwdefaults__)  # None

def bar(name="古明地覺", *, age=16):
    pass
print(bar.__kwdefaults__)  # {'age': 16}

加上一個 * 表示后面的參數必須通過關鍵字的方式傳遞。

func_closure:一個元組,包含了內層函數使用的外層作用域的變量,即 cell 變量。

def foo():
    name = "古明地覺"
    age = 17

    def bar():
        print(name, age)

    return bar


# 內層函數 bar 使用了外層作用域中的 name、age 變量
print(foo().__closure__)
"""
(<cell at 0x000001FD1D3B02B0: int object at 0x7efe79d4a1c8>,
 <cell at 0x000001FD1D42E310: str object at 0x7efe7921bc30>)
"""

print(foo().__closure__[0].cell_contents)  # 17
print(foo().__closure__[1].cell_contents)  # 古明地覺

注意:查看閉包屬性我們使用的是內層函數。

func_doc:函數的 docstring

def foo():
    """
    hi,歡迎來到我的小屋
    遇見你真好
    """
    pass

print(foo.__doc__)
"""
    hi,歡迎來到我的小屋
    遇見你真好
"""

當我們在寫 Python 擴展的時候,由于編譯之后是一個 pyd,那么就會通過 docstring 來描述函數的相關信息。

func_dict:函數的屬性字典

def foo(name, age):
    pass

print(foo.__dict__)  # {}

函數在底層也是由一個類實例化得到的,所以它也可以有自己的屬性字典,只不過這個字典一般為空。

func_module:函數所在的模塊

import numpy as np

print(np.array.__module__)  # numpy

除了函數,類、方法、協程也有 __module__ 屬性。

func_annotations:類型注解

def foo(name: str, age: int):
    pass

# Python3.5 新增的語法,但只能用于函數參數
# 而在 3.6 的時候,聲明變量也可以使用這種方式
# 特別是當 IDE 無法得知返回值類型時,便可通過類型注解的方式告知 IDE
# 這樣就又能使用 IDE 的智能提示了
print(
    foo.__annotations__
)  # {'name': <class 'str'>, 'age': <class 'int'>}

像 FastAPI、Pydantic 等框架,都大量應用了類型注解。

func_typeparams:類型參數

from typing import TypeVar

T = TypeVar('T')
S = TypeVar('S')


def foo[T, S](x: T, y: S) -> list[S, T]:
    return (y, x)

print(foo.__type_params__)  # (T, S)


class A[T, S]:
    def __init__(self, x: T, y: S):
        self.x: T = x
        self.y: S = y

a1 = A[int, float](3, 2.71)
a2 = A[str, dict]("hello", {})
print(A.__type_params__)  # (T, S)
print(a1.__type_params__)  # (T, S)
print(a2.__type_params__)  # (T, S)

關于類型參數的更具體用法,可以查閱相關文檔,說實話如果是在 Python 里面,這種語法我估計一輩子都不會用。

vectorcallfunc vectorcall:矢量調用協議

函數本質上也是一個實例對象,在調用時會執行類型對象的 tp_call,對應 Python 里的 __call__。但 tp_call 屬于通用邏輯,而通用往往也意味著平庸,tp_call 在執行時需要創建臨時元組和臨時字典來存儲位置參數、關鍵字參數,這些臨時對象增加了內存分配和垃圾回收的開銷。

如果只是一般的實例對象倒也沒什么,但函數不同,它作為實例對象注定是要被調用的。所以底層對它進行了優化,引入了速度更快的 vectorcall,即矢量調用。

關于普通調用(tp_call)和矢量調用(vectorcall)的具體細節,后續會詳細說明??傊粋€實例對象如果支持矢量調用,那么它也必須支持普通調用,并且兩者的結果是一致的,當對象不支持矢量調用時,會退化成普通調用。

uint32_t func_version:版本號,用于函數特化

函數特化是指根據函數的調用模式,生成更高效的特定版本代碼,特別是針對那些頻繁調用的函數。但函數特化有一個前提,就是函數本身不能夠發生改變,于是引入了 func_version 字段。

當函數的某些字段的值發生改變時,func_version 會重置為 0,而當底層看到 func_version 為 0 時,就知道函數發生改變了,特化失效。

def foo(x, y=10):
    return x + y

# 以下操作會將 func_version 重置為 0

# 1. 修改默認參數
foo.__defaults__ = (20,)

# 2. 修改關鍵字默認參數
# 注:必須是指向一個新的字典,版本號才會重置
foo.__kwdefaults__ = {"z": 30}

# 3. 修改代碼對象
# (幾乎不可能直接修改,但可以通過某些高級技巧)

# 4. 修改注解
foo.__annotations__["return"] = int

# 5. 修改 vectorcall 函數指針
# (這是 C 級別的操作,Python 代碼通常無法直接觸及)

所以只要函數保持不變,Python 就會用特化版本來優化執行,而我們在工作中基本也不會修改上面這幾個字段。

小結

以上就是函數的底層結構,在 Python 里面是由 <class 'function'> 實例化得到的。

def foo(name, age):
    pass

# <class 'function'> 就是 C 里面的 PyFunction_Type
print(foo.__class__)  # <class 'function'>

但這個類底層沒有暴露給我們,我們不能直接用,因為函數通過 def 創建即可,不需要通過類型對象來創建。

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

2024-08-08 11:05:22

2024-05-07 09:24:12

Python源碼Java

2021-08-09 18:42:57

React VueSvelte

2024-07-24 09:34:27

2020-11-16 09:28:41

函數內存

2020-04-09 11:00:20

Java虛擬機對象

2022-03-15 16:19:13

物聯網物聯網 2.0IoT

2011-10-10 11:04:54

2022-05-30 18:54:12

元宇宙Web3數據量

2022-10-10 08:47:49

ITCIO數據

2018-04-11 15:22:58

2021-09-14 16:32:11

物聯網IOT

2022-04-08 09:59:03

物聯網2.0物聯網

2021-02-19 10:14:49

云計算公共云

2021-05-08 13:11:58

物聯網IOT物聯網技術

2018-11-28 14:53:44

物聯網網關物聯網IOT

2012-10-29 15:45:51

2021-11-29 07:42:44

CSS 技巧CSS 繪圖技巧

2021-10-04 15:46:31

網絡通信5G

2018-01-16 15:02:20

存儲RAIDSAN
點贊
收藏

51CTO技術棧公眾號

色综合一个色综合亚洲| 成人免费高清视频在线观看| 色吧影院999| 日韩av影视大全| 国产在线美女| 国产精品女主播在线观看| 51精品国产人成在线观看| 国产成人无码精品亚洲| 青青草91久久久久久久久| 日韩精品一区二区三区在线播放| 免费高清在线观看免费| 巨大荫蒂视频欧美大片| 91在线云播放| 国产在线98福利播放视频| 中日韩黄色大片| 一个色综合网| 在线观看久久久久久| 国产伦理在线观看| 国产精品一区二区免费福利视频| 亚洲国产你懂的| 亚洲欧洲精品在线观看| 神马精品久久| 久久精品国产一区二区三| 97色在线视频观看| 日韩影院一区二区| 极品美女一区二区三区| 精品国产一区二区在线观看| 香港日本韩国三级网站| 国产第一页在线| 国产精品第四页| 欧美亚洲另类在线一区二区三区| 国产精品一区二区黑人巨大| 久久综合图片| 98精品在线视频| 久草网在线观看| 91精品综合久久久久久久久久久| 精品爽片免费看久久| 国产成人av片| 欧美久久亚洲| 日韩午夜小视频| 中文字幕精品一区二区三区在线| 中文字幕乱码中文乱码51精品| 一卡二卡三卡日韩欧美| 综合色婷婷一区二区亚洲欧美国产| 精品欧美不卡一区二区在线观看| 99久久婷婷国产| 国产九区一区在线| 欧美 日韩 国产 成人 在线| 成人一区二区三区中文字幕| 91原创国产| av中文字幕观看| 国产一区二区精品久久91| 成人国产在线视频| 91精品国自产| 黄网站免费久久| 成人免费淫片视频软件| 国产精品欧美激情在线| 国内成+人亚洲+欧美+综合在线| 国产精品极品在线| 中文字幕福利视频| 久久99在线观看| 91亚洲精华国产精华| 国产99久一区二区三区a片| 国内成人免费视频| 成人免费观看网站| 好男人www在线视频| 99视频一区二区| 热re99久久精品国99热蜜月| 福利在线午夜| 国产精品久久久久一区| 致1999电视剧免费观看策驰影院| 精品视频在线一区二区| 亚洲综合精品久久| 国产成人精品视频免费看| 日韩一区二区三区免费| 欧美日韩亚洲综合在线| 欧美人与性动交α欧美精品| 国产精品黄网站| 亚洲欧美自拍一区| 天海翼在线视频| 欧美视频四区| 91精品国产91久久久久| 天天天天天天天干| 国产主播一区二区| 九色91视频| 成年人视频网站在线| 亚洲桃色在线一区| 日本www在线视频| 日韩av超清在线观看| 日韩一区二区三区视频| 国产又爽又黄无码无遮挡在线观看| 国产欧美日韩视频在线| 美日韩精品免费视频| 国产精品第一页在线观看| 日韩精品乱码免费| 亚洲自拍偷拍在线| 国产午夜精品一区理论片| 亚洲人成在线播放网站岛国| 亚洲熟妇av日韩熟妇在线| 欧美一级做a| 日韩电影免费观看中文字幕 | 91精品国产高清一区二区三密臀| 日韩国产在线观看| 国产精品久久国产三级国电话系列| 日韩美女一级视频| 亚洲久草在线视频| 熟妇人妻va精品中文字幕| 亚洲三区欧美一区国产二区| 亚洲欧美综合区自拍另类| 久草资源在线视频| 九九热在线视频观看这里只有精品 | 五月天综合激情| 国产尤物一区二区| 日韩中文一区二区三区| 麻豆av在线播放| 欧美精品色综合| 色无极影院亚洲| 狠狠入ady亚洲精品| 91精品久久久久久久久久另类| 人妻精品一区二区三区| 中文字幕日韩一区| www.xxx亚洲| 噜噜噜狠狠夜夜躁精品仙踪林| 美日韩精品免费观看视频| 中文无码精品一区二区三区| 久久这里只有精品6| 精品国偷自产一区二区三区| 二区三区精品| www.99久久热国产日韩欧美.com| 日韩手机在线视频| 波多野结衣一区二区三区 | 国产精品.com| 哥也色在线视频| 欧美三级视频在线播放| a毛片毛片av永久免费| 国产日韩一区二区三区在线播放| 粉嫩av免费一区二区三区| 精品176二区| 欧美高清一级片在线| 欧美88888| 男女男精品视频网| 亚洲精蜜桃久在线| 91精品美女| 在线视频免费一区二区| 久久久精品毛片| 久久久噜噜噜久久中文字幕色伊伊 | 欧美亚男人的天堂| 蜜桃传媒一区二区亚洲| 乱码第一页成人| 蜜桃导航-精品导航| 自拍在线观看| 亚洲欧洲偷拍精品| 日本丰满少妇做爰爽爽| 欧美激情在线免费观看| www欧美激情| 婷婷综合网站| 亚洲资源在线看| 黄色成人在线网| 亚洲的天堂在线中文字幕| 日本系列第一页| 91丨porny丨户外露出| 可以在线看的av网站| 少妇精品导航| 国产精品极品在线| 国产婷婷视频在线 | 美女伦理水蜜桃4| 99精品视频免费观看视频| 久久精品99| 国产成人精选| 久久艹在线视频| 欧美一级免费片| 欧美日韩亚洲精品一区二区三区| 中文字幕国产综合| 狠狠色狠狠色综合系列| 白白操在线视频| 欧洲亚洲一区二区三区| 国产成人久久久| 精品视频在线一区二区| 精品乱人伦小说| 免费的毛片视频| 中文字幕一区二区三中文字幕| 亚洲成人av免费观看| 国产午夜精品一区二区三区欧美| 水蜜桃一区二区三区| 日韩精品一区二区三区中文 | 91视频免费观看| 男人天堂成人在线| 欧美激情第10页| 麻豆视频成人| 国产精品高清一区二区| 91精品国产电影| 欧美13一16娇小xxxx| 日韩av网址在线| 91亚洲国产成人久久精品麻豆| 亚洲一区二区三区不卡国产欧美| 国产肥白大熟妇bbbb视频| 国产专区综合网| 情侣黄网站免费看| 韩国av一区| 亚洲成人第一| 丝袜美腿一区二区三区动态图| 国产欧美亚洲精品| 亚洲精品成人图区| 久久97久久97精品免视看| 久草在线免费福利资源| 日韩精品影音先锋| 一级黄色片免费看| 日韩欧美精品免费在线| 黄色一级片在线免费观看| 亚洲国产精华液网站w| 国产二级一片内射视频播放| 精品中文av资源站在线观看| 男人操女人免费| 最新国产拍偷乱拍精品| 异国色恋浪漫潭| 欧美伦理在线视频| 久久香蕉综合色| jizz性欧美2| 成人亚洲综合色就1024| 国精产品一区一区三区四川| 韩国精品久久久999| 色爱综合区网| 久久综合网hezyo| 尤物网址在线观看| 亚洲社区在线观看| 天堂av在线播放| 精品国产污网站| 成人av无码一区二区三区| 欧美另类z0zxhd电影| 在线观看免费中文字幕| 91福利在线播放| 免费看一级视频| 福利一区视频在线观看| 国产精品美女毛片真酒店| 亚洲男人的天堂网| 2021亚洲天堂| 亚洲女与黑人做爰| 五月天婷婷色综合| 一区二区三区四区乱视频| 四虎影院中文字幕| 亚洲色图视频网| 小泽玛利亚一区| 亚洲男女一区二区三区| 天堂网avav| 亚洲狠狠丁香婷婷综合久久久| fc2ppv在线播放| 亚洲另类色综合网站| 男女羞羞免费视频| 一区二区不卡在线播放| 日韩av黄色片| 狠狠做深爱婷婷久久综合一区| 国产无人区码熟妇毛片多| 午夜成人在线视频| 三级视频在线观看| 一本色道久久综合亚洲91| 亚洲自拍一区在线观看| 在线观看不卡视频| 一本一道人人妻人人妻αv| 欧美精品色综合| www.我爱av| 日韩av在线免费观看| 免费在线观看污视频| 国产亚洲视频中文字幕视频| 日本在线免费看| 欧美成人精品在线| ririsao久久精品一区| 69视频在线播放| 日本欧美韩国| 91久久精品久久国产性色也91| 精品国产一区二区三区性色av| 成人免费在线一区二区三区| 色婷婷精品视频| 在线看视频不卡| 亚洲午夜伦理| 婷婷丁香激情网| 国产精品一二三四区| 无码精品一区二区三区在线播放| 久久精品在线免费观看| 91香蕉视频污在线观看| 亚洲午夜电影网| 成人午夜精品视频| 日韩欧美专区在线| 女人偷人在线视频| 久久香蕉国产线看观看av| 草美女在线观看| 国产精品久久久久久久久久小说| 国产精品一区二区三区www| 精品免费国产| 天天久久综合| 男人天堂网视频| 国产一区欧美二区| 国产精品揄拍100视频| 一区在线中文字幕| 特级西西444www大精品视频免费看| 欧美日韩亚洲综合在线| 五月天婷婷激情网| 麻豆国产va免费精品高清在线| 九色porny丨国产首页在线| 国产欧美日韩精品在线观看| 国产精品xxx在线观看| 亚洲精品乱码久久久久久蜜桃91 | 欧美激情亚洲自拍| 91成人在线| 久久本道综合色狠狠五月| 久久一区二区三区喷水| 国产精品-区区久久久狼| 国产成人精品一区二| 黄色片在线观看免费| 午夜私人影院久久久久| 99视频国产精品免费观看a| 亚洲精品永久免费精品| 国产又色又爽又黄刺激在线视频| 国产精品劲爆视频| 日韩av网站在线免费观看| 国产又粗又长又爽视频| 久久草av在线| 亚洲av毛片基地| 色综合婷婷久久| 色综合视频在线| 久久69精品久久久久久久电影好 | 久久精品国产免费| 欧美老熟妇乱大交xxxxx| 亚洲一区二区在线观看视频 | 肉大捧一出免费观看网站在线播放| 丝袜美腿亚洲综合| 日韩精品卡通动漫网站| 午夜视频久久久久久| www.四虎在线观看| 久久国产精品免费视频| 天堂久久一区| 一区二区三区在线视频111| 日韩精品欧美精品| 男人天堂av电影| 一本色道a无线码一区v| 日韩大片b站免费观看直播| 国内免费精品永久在线视频| 日韩欧美中文在线观看| 在线观看av的网址| 国产精品12区| 九九九在线视频| 日韩欧美一区二区视频| 在线h片观看| 99在线免费观看视频| 国产精品videosex极品| 国产艳妇疯狂做爰视频| 亚洲永久精品大片| 亚洲精品国产精品国| 国模精品视频一区二区| 欧美一区二区三区久久| 无码人妻丰满熟妇区96| 久久久久久久综合色一本| 久久久久久久久黄色| 亚洲一级片在线看| 久久不卡日韩美女| 91麻豆天美传媒在线| 国产成人8x视频一区二区| 亚洲国产精品午夜在线观看| 亚洲精品v欧美精品v日韩精品| 桃色av一区二区| 欧美中文娱乐网| 精品一区二区三区影院在线午夜| 亚洲一级生活片| 欧美精品一区二区精品网| 成人免费看视频网站| 亚洲欧美日产图| 国产在线麻豆精品观看| 精品人妻在线播放| 精品视频一区在线视频| 欧美黄色a视频| 国产freexxxx性播放麻豆 | 欧美日韩电影一区二区三区| 日韩av中文字幕一区二区 | 国产中文字幕在线看| 国产精品主播视频| 欧美激情综合色综合啪啪| 性色av蜜臀av色欲av| 欧美午夜精品免费| gogogogo高清视频在线| 国严精品久久久久久亚洲影视| 久久天天综合| 欧美在线视频第一页| 亚洲精品videossex少妇| 国产成人免费| 无码中文字幕色专区| 国产欧美日韩综合| 精品人妻一区二区三区浪潮在线 | 在线免费观看亚洲| 成熟丰满熟妇高潮xxxxx视频| 国产日韩一级二级三级| 精品久久国产视频| 日本精品在线视频| 亚洲视频在线免费| 91成人破解版| 精品少妇一区二区三区免费观看| 神马久久资源| 欧美国产视频一区| 国产精品视频yy9299一区| 色哟哟国产精品色哟哟| 成人a在线视频| 乱人伦精品视频在线观看|