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

一文帶你深度解密Python的字節(jié)碼

 更新時(shí)間:2022年12月14日 11:06:18   作者:古明地覺  
當(dāng)我們想要執(zhí)行一個(gè)?py?文件的時(shí)候,只需要在命令行中輸入?python?xxx.py?即可,但你有沒有想過(guò)這背后的流程是怎樣的呢?本文主要賀和大家來(lái)聊聊Python中的字節(jié)碼,感興趣的可以了解一下

楔子

當(dāng)我們想要執(zhí)行一個(gè) py 文件的時(shí)候,只需要在命令行中輸入 python xxx.py 即可,但你有沒有想過(guò)這背后的流程是怎樣的呢?

首先 py 文件不是一上來(lái)就直接執(zhí)行的,而是會(huì)先有一個(gè)編譯的過(guò)程,整個(gè)步驟如下:

這里我們看到了 Python 編譯器、Python 虛擬機(jī),而且我們平常還會(huì)說(shuō) Python 解釋器,那么三者之間有什么區(qū)別呢?

Python 編譯器負(fù)責(zé)將 Python 源代碼編譯成 PyCodeObject 對(duì)象,然后交給 Python 虛擬機(jī)來(lái)執(zhí)行。

那么 Python 編譯器和 Python 虛擬機(jī)都在什么地方呢?如果打開 Python 的安裝目錄,會(huì)發(fā)現(xiàn)有一個(gè) python.exe,點(diǎn)擊的時(shí)候會(huì)通過(guò)它來(lái)啟動(dòng)一個(gè)終端。

但問(wèn)題是這個(gè)文件大小還不到 100K,不可能容納一個(gè)編譯器加一個(gè)虛擬機(jī),所以下面還有一個(gè) python38.dll。沒錯(cuò),編譯器、虛擬機(jī)都藏身于 python38.dll 當(dāng)中。

因此 Python 雖然是解釋型語(yǔ)言,但也有編譯的過(guò)程。源代碼會(huì)被編譯器編譯成 PyCodeObject 對(duì)象,然后再交給虛擬機(jī)來(lái)執(zhí)行。而之所以要存在編譯,是為了讓虛擬機(jī)能更快速地執(zhí)行,比如在編譯階段常量都會(huì)提前分配好,而且還可以盡早檢測(cè)出語(yǔ)法上的錯(cuò)誤。

pyc 文件是什么

在 Python 開發(fā)時(shí),我們肯定都見過(guò)這個(gè) pyc 文件,它一般位于 __pycache__ 目錄中,那么 pyc 文件和 PyCodeObject 之間有什么關(guān)系呢?

首先我們都知道字節(jié)碼,虛擬機(jī)的執(zhí)行實(shí)際上就是對(duì)字節(jié)碼不斷解析的一個(gè)過(guò)程。然而除了字節(jié)碼之外,還應(yīng)該包含一些其它的信息,這些信息也是 Python 運(yùn)行的時(shí)候所必需的,比如常量、變量名等等。

我們常聽到 py 文件被編譯成字節(jié)碼,這句話其實(shí)不太嚴(yán)謹(jǐn),因?yàn)樽止?jié)碼只是一個(gè) PyBytesObject 對(duì)象、或者說(shuō)一段字節(jié)序列。但很明顯,光有字節(jié)碼是不夠的,還有很多的靜態(tài)信息也需要被收集起來(lái),它們整體被稱為 PyCodeObject。

而 PyCodeObject 對(duì)象中有一個(gè)成員 co_code,它是一個(gè)指針,指向了這段字節(jié)序列。但是這個(gè)對(duì)象除了有 co_code 指向的字節(jié)碼之外,還有很多其它成員,負(fù)責(zé)保存代碼涉及到的常量、變量(名字、符號(hào))等等。

但是問(wèn)題來(lái)了,難道每一次執(zhí)行都要將源文件編譯一遍嗎?如果沒有對(duì)源文件進(jìn)行修改的話,那么完全可以使用上一次的編譯結(jié)果。相信此時(shí)你能猜到 pyc 文件是干什么的了,它就是負(fù)責(zé)保存編譯之后的 PyCodeObject 對(duì)象。

所以我們知道了,pyc 文件里面的內(nèi)容是 PyCodeObject 對(duì)象。對(duì)于 Python 編譯器來(lái)說(shuō),PyCodeObject 對(duì)象是對(duì)源代碼編譯之后的結(jié)果,而 pyc 文件則是這個(gè)對(duì)象在硬盤上的表現(xiàn)形式。

當(dāng)下一次運(yùn)行的時(shí)候,Python 會(huì)根據(jù) pyc 文件中記錄的編譯結(jié)果直接建立內(nèi)存中的 PyCodeObject 對(duì)象,而不需要再重新編譯了,當(dāng)然前提是沒有對(duì)源文件進(jìn)行修改。

PyCodeObject 底層結(jié)構(gòu)

我們來(lái)看一下這個(gè)結(jié)構(gòu)體長(zhǎng)什么樣子,它的定義位于 Include/code.h 中。

typedef?struct?{
????//頭部信息,我們看到真的一切皆對(duì)象,字節(jié)碼也是個(gè)對(duì)象
????PyObject_HEAD????
????//可以通過(guò)位置參數(shù)傳遞的參數(shù)個(gè)數(shù)
????int?co_argcount;????????????
????//只能通過(guò)位置參數(shù)傳遞的參數(shù)個(gè)數(shù),Python3.8新增
????int?co_posonlyargcount;?????
????//只能通過(guò)關(guān)鍵字參數(shù)傳遞的參數(shù)個(gè)數(shù)
????int?co_kwonlyargcount;?????
????//代碼塊中局部變量的個(gè)數(shù),也包括參數(shù)
????int?co_nlocals;?????????????
????//執(zhí)行該段代碼塊需要的棧空間
????int?co_stacksize;??????
????//參數(shù)類型標(biāo)識(shí)????
????int?co_flags;???????????
????//代碼塊在文件中的行號(hào)??
????int?co_firstlineno;?????????
????//指令集,也就是字節(jié)碼,它是一個(gè)bytes對(duì)象?
????PyObject?*co_code;?????????
????//常量池,一個(gè)元組,保存代碼塊中的所有常量?
????PyObject?*co_consts;???????
????//一個(gè)元組,保存代碼塊中引用的其它作用域的變量
????PyObject?*co_names;??????
????//一個(gè)元組,保存當(dāng)前作用域中的變量???
????PyObject?*co_varnames;????
????//內(nèi)層函數(shù)引用的外層函數(shù)的作用域中的變量
????PyObject?*co_freevars;??????
????//外層函數(shù)的作用域中被內(nèi)層函數(shù)引用的變量
????//本質(zhì)上和co_freevars是一樣的
????PyObject?*co_cellvars;??????
????//無(wú)需關(guān)注
????Py_ssize_t?*co_cell2arg;????
????//代碼塊所在的文件名
????PyObject?*co_filename;????
????//代碼塊的名字,通常是函數(shù)名、類名,或者文件名
????PyObject?*co_name;?????????
????//字節(jié)碼指令與python源代碼的行號(hào)之間的對(duì)應(yīng)關(guān)系
????//以PyByteObject的形式存在?
????PyObject?*co_lnotab;????????
}?PyCodeObject;

這里面的每一個(gè)成員,我們一會(huì)兒都會(huì)逐一演示進(jìn)行說(shuō)明??傊?Python 編譯器在對(duì)源代碼進(jìn)行編譯的時(shí)候,對(duì)于代碼中的每一個(gè) block,都會(huì)創(chuàng)建一個(gè) PyCodeObject 與之對(duì)應(yīng)。

但多少代碼才算得上是一個(gè) block 呢?事實(shí)上,Python 有一個(gè)簡(jiǎn)單而清晰的規(guī)則:當(dāng)進(jìn)入一個(gè)新的名字空間,或者說(shuō)作用域時(shí),就算是進(jìn)入了一個(gè)新的 block 了。舉個(gè)例子:

class?A:
????a?=?123

def?foo():
????a?=?[]

我們仔細(xì)觀察一下上面這個(gè)文件,它在編譯完之后會(huì)有三個(gè) PyCodeObject 對(duì)象,一個(gè)是對(duì)應(yīng)整個(gè) py 文件(模塊)的,一個(gè)是對(duì)應(yīng) class A 的,一個(gè)是對(duì)應(yīng) def foo 的。因?yàn)檫@是三個(gè)不同的作用域,所以會(huì)有三個(gè) PyCodeObject 對(duì)象。

所以一個(gè) code block 對(duì)應(yīng)一個(gè)作用域、同時(shí)也對(duì)應(yīng)一個(gè) PyCodeObject 對(duì)象。Python 的類、函數(shù)、模塊都有自己獨(dú)立的作用域,因此在編譯時(shí)也都會(huì)有一個(gè) PyCodeObject 對(duì)象與之對(duì)應(yīng)。

PyCodeObject 代碼演示

PyCodeObject 我們知道它是干什么的了,那如何才能拿到這個(gè)對(duì)象呢?首先該對(duì)象在 Python 里面的類型是 <class 'code'>,但是底層沒有將這個(gè)類暴露給我們,因此 code 這個(gè)名字在 Python 里面只是一個(gè)沒有定義的變量罷了。

但是我們可以通過(guò)其它的方式進(jìn)行獲取,比如函數(shù)。

def?func():
????pass

print(func.__code__)??#?<code?object?......
print(type(func.__code__))??#?<class?'code'>

我們可以通過(guò)函數(shù)的 __code__ 屬性拿到底層對(duì)應(yīng)的PyCodeObject對(duì)象,當(dāng)然也可以獲取里面的成員,我們來(lái)演示一下。

co_argcount:可以通過(guò)位置參數(shù)傳遞的參數(shù)個(gè)數(shù)

def?foo(a,?b,?c=3):
????pass
print(foo.__code__.co_argcount)??#?3

def?bar(a,?b,?*args):
????pass
print(bar.__code__.co_argcount)??#?2

def?func(a,?b,?*args,?c):
????pass
print(func.__code__.co_argcount)??#?2

foo 中的參數(shù) a、b、c 都可以通過(guò)位置參數(shù)傳遞,所以結(jié)果是 3;對(duì)于 bar,則是兩個(gè),這里不包括 *args;而函數(shù) func,顯然也是兩個(gè),因?yàn)閰?shù) c 只能通過(guò)關(guān)鍵字參數(shù)傳遞。

co_posonlyargcount:只能通過(guò)位置參數(shù)傳遞的參數(shù)個(gè)數(shù),Python3.8 新增

def?foo(a,?b,?c):
????pass

print(foo.__code__.co_posonlyargcount)??#?0

def?bar(a,?b,?/,?c):
????pass

print(bar.__code__.co_posonlyargcount)??#?2

注意:這里是只能通過(guò)位置參數(shù)傳遞的參數(shù)個(gè)數(shù)。對(duì)于 foo 而言,里面的三個(gè)參數(shù)既可以通過(guò)位置參數(shù)、也可以通過(guò)關(guān)鍵字參數(shù)傳遞;而函數(shù) bar,里面的 a、b 只能通過(guò)位置參數(shù)傳遞。

co_kwonlyargcount:只能通過(guò)關(guān)鍵字參數(shù)傳遞的參數(shù)個(gè)數(shù)

def?foo(a,?b=1,?c=2,?*,?d,?e):
????pass
print(foo.__code__.co_kwonlyargcount)??#?2

這里是 d 和 e,它們必須通過(guò)關(guān)鍵字參數(shù)傳遞。

co_nlocals:代碼塊中局部變量的個(gè)數(shù),也包括參數(shù)

def?foo(a,?b,?*,?c):
????name?=?"xxx"
????age?=?16
????gender?=?"f"
????c?=?33

print(foo.__code__.co_nlocals)??#?6

局部變量有 a、b、c、name、age、gender,所以我們看到在編譯之后,函數(shù)的局部變量就已經(jīng)確定了,因?yàn)樗鼈兪庆o態(tài)存儲(chǔ)的。

co_stacksize:執(zhí)行該段代碼塊需要的棧空間

def?foo(a,?b,?*,?c):
????name?=?"xxx"
????age?=?16
????gender?=?"f"
????c?=?33

print(foo.__code__.co_stacksize)??#?1

這個(gè)暫時(shí)不需要太關(guān)注。

co_flags:參數(shù)類型標(biāo)識(shí)

標(biāo)識(shí)函數(shù)的參數(shù)類型,如果一個(gè)函數(shù)的參數(shù)出現(xiàn)了 *args,那么 co_flags & 0x04 為真;如果一個(gè)函數(shù)的參數(shù)出現(xiàn)了 **kwargs,那么 co_flags & 0x08 為真;

def?foo1():
????pass
#?結(jié)果全部為假
print(foo1.__code__.co_flags?&?0x04)??#?0
print(foo1.__code__.co_flags?&?0x08)??#?0

def?foo2(*args):
????pass
#?co_flags?&?0x04?為真,因?yàn)槌霈F(xiàn)了?*args
print(foo2.__code__.co_flags?&?0x04)??#?4
print(foo2.__code__.co_flags?&?0x08)??#?0

def?foo3(*args,?**kwargs):
????pass
#?顯然?co_flags?&?0x04?和?co_flags?&?0x08?均為真
print(foo3.__code__.co_flags?&?0x04)??#?4
print(foo3.__code__.co_flags?&?0x08)??#?8

當(dāng)然啦,co_flags 可以做的事情并不止這么簡(jiǎn)單,它還能檢測(cè)一個(gè)函數(shù)的類型。比如函數(shù)內(nèi)部出現(xiàn)了 yield,那么它就是一個(gè)生成器函數(shù),調(diào)用之后可以得到一個(gè)生成器;使用 async def 定義,那么它就是一個(gè)協(xié)程函數(shù),調(diào)用之后可以得到一個(gè)協(xié)程。

這些在詞法分析的時(shí)候就可以檢測(cè)出來(lái),編譯之后會(huì)體現(xiàn)在 co_flags 這個(gè)成員中。

#?如果是生成器函數(shù)
#?那么?co_flags?&?0x20?為真
def?foo1():
????yield
print(foo1.__code__.co_flags?&?0x20)??#?32

#?如果是協(xié)程函數(shù)
#?那么?co_flags?&?0x80?為真
async?def?foo2():
????pass
print(foo2.__code__.co_flags?&?0x80)??#?128
#?顯然?foo2?不是生成器函數(shù)
#?所以?co_flags?&?0x20?為假
print(foo2.__code__.co_flags?&?0x20)??#?0

#?如果是異步生成器函數(shù)
#?那么?co_flags?&?0x200?為真
async?def?foo3():
????yield
print(foo3.__code__.co_flags?&?0x200)??#?512
#?顯然它不是生成器函數(shù)、也不是協(xié)程函數(shù)
#?因此和?0x20、0x80?按位與之后,結(jié)果都為假
print(foo3.__code__.co_flags?&?0x20)??#?0
print(foo3.__code__.co_flags?&?0x80)??#?0

在判斷函數(shù)種類時(shí),這種方式是最優(yōu)雅的。

co_firstlineno:代碼塊在對(duì)應(yīng)文件的起始行

def?foo(a,?b,?*,?c):
????pass

#?顯然是文件的第一行
#?或者理解為?def?所在的行
print(foo.__code__.co_firstlineno)??#?1

如果函數(shù)出現(xiàn)了調(diào)用呢?

def?foo():
????return?bar

def?bar():
????pass

print(foo().__code__.co_firstlineno)??#?4

如果執(zhí)行 foo,那么會(huì)返回函數(shù) bar,最終得到的就是 bar 的字節(jié)碼,因此最終結(jié)果是 def bar(): 所在的行數(shù)。所以每個(gè)函數(shù)都有自己的作用域,以及 PyCodeObject 對(duì)象。

co_names:符號(hào)表,一個(gè)元組,保存代碼塊中引用的其它作用域的變量

c?=?1

def?foo(a,?b):
????print(a,?b,?c)
????d?=?(list,?int,?str)

print(
????foo.__code__.co_names
)??#?('print',?'c',?'list',?'int',?'str')

一切皆對(duì)象,但看到的都是指向?qū)ο蟮淖兞?,所?print, c, list, int, str 都是變量,它們都不在當(dāng)前 foo 函數(shù)的作用域中。

co_varnames:符號(hào)表,一個(gè)元組,保存在當(dāng)前作用域中的變量

c?=?1

def?foo(a,?b):
????print(a,?b,?c)
????d?=?(list,?int,?str)
print(foo.__code__.co_varnames)??#?('a',?'b',?'d')

a、b、d 是位于當(dāng)前 foo 函數(shù)的作用域當(dāng)中的,所以編譯階段便確定了局部變量是什么。

co_consts:常量池,一個(gè)元組,保存代碼塊中的所有常量

x?=?123

def?foo(a,?b):
????c?=?"abc"
????print(x)
????print(True,?False,?list,?[1,?2,?3],?{"a":?1})
????return?">>>"

print(
????foo.__code__.co_consts
)??#?(None,?'abc',?True,?False,?1,?2,?3,?'a',?'>>>')

co_consts 里面出現(xiàn)的都是常量,但 [1, 2, 3] 和 {"a": 1} 卻沒有出現(xiàn),由此我們可以得出,列表和字典絕不是在編譯階段構(gòu)建的。編譯時(shí),只是收集了里面的元素,然后等到運(yùn)行時(shí)再去動(dòng)態(tài)構(gòu)建。

不過(guò)問(wèn)題來(lái)了,在構(gòu)建的時(shí)候解釋器怎么知道是要構(gòu)建列表、還是字典、亦或是其它的什么對(duì)象呢?所以這就依賴于字節(jié)碼了,解釋字節(jié)碼的時(shí)候,會(huì)判斷到底要構(gòu)建什么樣的對(duì)象。

因此解釋器執(zhí)行的是字節(jié)碼,核心邏輯都體現(xiàn)在字節(jié)碼中。但是光有字節(jié)碼還不夠,它包含的只是程序的主干邏輯,至于變量、常量,則從符號(hào)表和常量池里面獲取。

co_name:代碼塊的名字

def?foo():
????pass
#?這里就是函數(shù)名
print(foo.__code__.co_name)??#?foo

co_code:字節(jié)碼

def?foo(a,?b,?/,?c,?*,?d,?e):
????f?=?123
????g?=?list()
????g.extend([tuple,?getattr,?print])

print(foo.__code__.co_code)
#b'd\x01}\x05t\x00\x83\x00}\x06|\x06......'

這便是字節(jié)碼,它只保存了要操作的指令,因此光有字節(jié)碼是肯定不夠的,還需要其它的靜態(tài)信息。顯然這些信息連同字節(jié)碼一樣,都位于 PyCodeObject 中。

字節(jié)碼與反編譯

Python 執(zhí)行源代碼之前會(huì)先編譯得到 PyCodeObject 對(duì)象,里面的 co_code 指向了字節(jié)碼序列。

虛擬機(jī)會(huì)根據(jù)這些字節(jié)碼序列來(lái)進(jìn)行一系列的操作(當(dāng)然也依賴其它的靜態(tài)信息),從而完成對(duì)程序的執(zhí)行。

每個(gè)操作都對(duì)應(yīng)一個(gè)操作指令、也叫操作碼,總共有120多種,定義在 Include/opcode.h 中。

#define?POP_TOP???????????????????1
#define?ROT_TWO???????????????????2
#define?ROT_THREE?????????????????3
#define?DUP_TOP???????????????????4
#define?DUP_TOP_TWO???????????????5
#define?NOP???????????????????????9
#define?UNARY_POSITIVE???????????10
#define?UNARY_NEGATIVE???????????11
#define?UNARY_NOT????????????????12
#define?UNARY_INVERT?????????????15
#define?BINARY_MATRIX_MULTIPLY???16
#define?INPLACE_MATRIX_MULTIPLY??17
#define?BINARY_POWER?????????????19
#define?BINARY_MULTIPLY??????????20
#define?BINARY_MODULO????????????22
#define?BINARY_ADD???????????????23
#define?BINARY_SUBTRACT??????????24
#define?BINARY_SUBSCR????????????25
#define?BINARY_FLOOR_DIVIDE??????26
#define?BINARY_TRUE_DIVIDE???????27
#define?INPLACE_FLOOR_DIVIDE?????28
//?...
//?...

操作指令只是一個(gè)整數(shù),然后我們可以通過(guò)反編譯的方式查看每行 Python 代碼都對(duì)應(yīng)哪些操作指令:

#?Python中的dis模塊專門負(fù)責(zé)干這件事情
import?dis

def?foo(a,?b):
????c?=?a?+?b
????return?c

#?里面接收一個(gè)字節(jié)碼
#?當(dāng)然函數(shù)也是可以的,會(huì)自動(dòng)獲取co_code
dis.dis(foo)
"""
??5???????????0?LOAD_FAST????????????????0?(a)
??????????????2?LOAD_FAST????????????????1?(b)
??????????????4?BINARY_ADD
??????????????6?STORE_FAST???????????????2?(c)

??6???????????8?LOAD_FAST????????????????2?(c)
?????????????10?RETURN_VALUE
"""

字節(jié)碼反編譯后的結(jié)果多么像匯編語(yǔ)言,其中第一列是源代碼行號(hào),第二列是字節(jié)碼偏移量,第三列是操作指令(也叫操作碼),第四列是指令參數(shù)(也叫操作數(shù))。Python 的字節(jié)碼指令都是成對(duì)出現(xiàn)的,每個(gè)指令都會(huì)帶有一個(gè)指令參數(shù)。

查看字節(jié)碼也可以使用 opcode 模塊:

from?opcode?import?opmap

opmap?=?{v:?k?for?k,?v?in?opmap.items()}

def?foo(a,?b):
????c?=?a?+?b
????return?c

code?=?foo.__code__.co_code
for?i?in?range(0,?len(code),?2):
????print("操作碼:?{:<12}?操作數(shù):?{}".format(
????????opmap[code[i]],?code[i+1]
????))
"""
操作碼:?LOAD_FAST????操作數(shù):?0
操作碼:?LOAD_FAST????操作數(shù):?1
操作碼:?BINARY_ADD???操作數(shù):?0
操作碼:?STORE_FAST???操作數(shù):?2
操作碼:?LOAD_FAST????操作數(shù):?2
操作碼:?RETURN_VALUE?操作數(shù):?0
"""

總之字節(jié)碼就是一段字節(jié)序列,轉(zhuǎn)成列表之后就是一堆數(shù)字。偶數(shù)位置表示指令本身,而每個(gè)指令后面都會(huì)跟一個(gè)指令參數(shù),也就是奇數(shù)位置表示指令參數(shù)。

所以指令本質(zhì)上只是一個(gè)整數(shù):

虛擬機(jī)會(huì)根據(jù)不同的指令執(zhí)行不同的邏輯,說(shuō)白了 Python 虛擬機(jī)執(zhí)行字節(jié)碼的邏輯就是把自己想象成一顆 CPU,并內(nèi)置了一個(gè)巨型的 switch case 語(yǔ)句,其中每個(gè)指令都對(duì)應(yīng)一個(gè) case 分支。

然后遍歷整條字節(jié)碼,拿到每一個(gè)指令和指令參數(shù)。然后對(duì)指令進(jìn)行判斷,不同的指令進(jìn)入不同的 case 分支,執(zhí)行不同的處理邏輯,直到字節(jié)碼全部執(zhí)行完畢或者程序出錯(cuò)。

到此這篇關(guān)于一文帶你深度解密Python的字節(jié)碼的文章就介紹到這了,更多相關(guān)Python字節(jié)碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python連接mysql數(shù)據(jù)庫(kù)并讀取數(shù)據(jù)的實(shí)現(xiàn)

    python連接mysql數(shù)據(jù)庫(kù)并讀取數(shù)據(jù)的實(shí)現(xiàn)

    這篇文章主要介紹了python連接mysql數(shù)據(jù)庫(kù)并讀取數(shù)據(jù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • python實(shí)現(xiàn)機(jī)器學(xué)習(xí)之元線性回歸

    python實(shí)現(xiàn)機(jī)器學(xué)習(xí)之元線性回歸

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)機(jī)器學(xué)習(xí)之元線性回歸,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解

    educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解

    這篇文章主要為大家介紹了educoder之Python數(shù)值計(jì)算庫(kù)Numpy圖像處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • python實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲

    python實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Python破解極驗(yàn)滑動(dòng)驗(yàn)證碼詳細(xì)步驟

    Python破解極驗(yàn)滑動(dòng)驗(yàn)證碼詳細(xì)步驟

    學(xué)習(xí)python知識(shí)越來(lái)越多,大家都知道極驗(yàn)驗(yàn)證碼應(yīng)用非常廣泛,今天小編就給大家分享Python破解極驗(yàn)滑動(dòng)驗(yàn)證碼的詳細(xì)步驟,對(duì)Python極驗(yàn)滑動(dòng)驗(yàn)證碼相關(guān)知識(shí)感興趣的朋友一起看看吧
    2021-05-05
  • Python類型轉(zhuǎn)換的魔術(shù)方法詳解

    Python類型轉(zhuǎn)換的魔術(shù)方法詳解

    這篇文章主要介紹了Python類型轉(zhuǎn)換的魔術(shù)方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • pandas修改DataFrame列名的方法

    pandas修改DataFrame列名的方法

    下面小編就為大家分享一篇pandas修改DataFrame列名的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • python雙向鏈表實(shí)現(xiàn)實(shí)例代碼

    python雙向鏈表實(shí)現(xiàn)實(shí)例代碼

    python雙向鏈表和單鏈表類似,只不過(guò)是增加了一個(gè)指向前面一個(gè)元素的指針,下面的代碼實(shí)例了python雙向鏈表的方法
    2013-11-11
  • Python 網(wǎng)頁(yè)解析HTMLParse的實(shí)例詳解

    Python 網(wǎng)頁(yè)解析HTMLParse的實(shí)例詳解

    這篇文章主要介紹了Python 網(wǎng)頁(yè)解析HTMLParse的實(shí)例詳解的相關(guān)資料,python里提供了一個(gè)簡(jiǎn)單的解析模塊HTMLParser類,使用起來(lái)也是比較簡(jiǎn)單的,解析語(yǔ)法沒有用到XPath類似的簡(jiǎn)潔模式,需要的朋友可以參考下
    2017-08-08
  • python中使用xlrd讀excel使用xlwt寫excel的實(shí)例代碼

    python中使用xlrd讀excel使用xlwt寫excel的實(shí)例代碼

    這篇文章主要介紹了python中使用xlrd讀excel使用xlwt寫excel的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01

最新評(píng)論