亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Python: 淺談函數(shù)局部變量"快"在哪

NikoManiac / 1254人閱讀

摘要:毫無(wú)疑問(wèn)是全局,但是是什么鬼似乎應(yīng)該叫吧然而事實(shí)就是這么神奇,人家就真的是叫,因?yàn)榫植孔兞渴菑囊粋€(gè)叫的數(shù)組里面讀,故名字也這樣取了。所以我們?cè)谝恍?huì)頻繁操作類實(shí)例屬性的情況下,應(yīng)該是先把屬性取出來(lái)存到局部變量,然后用局部變量來(lái)完成操作。

前言

這兩天在 CodeReview 時(shí),看到這樣的代碼

# 偽代碼
import somelib
class A(object):
    def load_project(self):
        self.project_code_to_name = {}
        for project in somelib.get_all_projects():
            self.project_code_to_name[project] = project
        ...

意圖很簡(jiǎn)單,就是將 somelib.get_all_projects 獲取的項(xiàng)目塞入的 self.project_code_to_name

然而印象中這個(gè)是有優(yōu)化空間的,于是提出調(diào)整方案:

import somelib
class A(object):
    def load_project(self):
        project_code_to_name = {}
        for project in somelib.get_all_projects():
            project_code_to_name[project] = project
        self.project_code_to_name = project_code_to_name
        ...

方案很簡(jiǎn)單,就是先定義局部變量 project_code_to_name,操作完,再賦值到self.project_code_to_name。

在后面的測(cè)試,也確實(shí)發(fā)現(xiàn)這樣是會(huì)好點(diǎn),那么結(jié)果知道了,接下來(lái)肯定是想探索原因的!

局部變量

其實(shí)在網(wǎng)上很多地方,甚至很多書上都有講過(guò)一個(gè)觀點(diǎn):訪問(wèn)局部變量速度要快很多,粗看好像好有道理,然后又看到下面貼了一大堆測(cè)試數(shù)據(jù),雖然不知道是什么,但這是真的屌,記住再說(shuō),管他呢!

但是實(shí)際上這個(gè)觀點(diǎn)還是有一定的局限性,并不是放諸四海皆準(zhǔn)。所以先來(lái)理解下這句話吧,為什么大家都喜歡這樣說(shuō)。

先看段代碼理解下什么是局部變量:

#coding: utf8
a = 1
def test(b):
    c = "test"    
    print a   # 全局變量
    print b   # 局部變量
    print c   # 局部變量

test(3)
# 輸出
1
3
test
簡(jiǎn)單來(lái)說(shuō),局部變量就是只作用于所在的函數(shù)域,超過(guò)作用域就被回收

理解了什么是局部變量,就需要談?wù)?Python 函數(shù) 和 局部變量 的愛(ài)恨情仇,因?yàn)槿绻桓闱宄@個(gè),是很難感受到到底快在哪里;

為避免枯燥,以上述的代碼來(lái)闡述吧,順便附上 test 函數(shù)執(zhí)行 的 dis 的解析:

# CALL_FUNCTION

  5           0 LOAD_CONST               1 ("test")
              3 STORE_FAST               1 (c)

  6           6 LOAD_GLOBAL              0 (a)
              9 PRINT_ITEM
             10 PRINT_NEWLINE

  7          11 LOAD_FAST                0 (b)
             14 PRINT_ITEM
             15 PRINT_NEWLINE

  8          16 LOAD_FAST                1 (c)
             19 PRINT_ITEM
             20 PRINT_NEWLINE
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE

在上圖中比較清楚能看到 a、b、c 分別對(duì)應(yīng)的指令塊,每一塊的第一行都是 LOAD_XXX,顧名思義,是說(shuō)明這些變量是從哪個(gè)地方獲取的。

LOAD_GLOBAL 毫無(wú)疑問(wèn)是全局,但是 LOAD_FAST 是什么鬼?似乎應(yīng)該叫LOAD_LOCAL 吧?

然而事實(shí)就是這么神奇,人家就真的是叫 LOAD_FAST,因?yàn)榫植孔兞渴菑囊粋€(gè)叫 fastlocals 的數(shù)組里面讀,故名字也這樣取了。

那么是否存在這樣的一個(gè) LOAD_LOCAL

答案是有的,不過(guò)人家不叫這個(gè),而是叫LOAD_LOCALS,而且這個(gè)指令在這里卻是完全不同的含義,為何?

因?yàn)檫@個(gè)指令幾乎不會(huì)在函數(shù)運(yùn)行出現(xiàn),而是在類定義時(shí)才會(huì)出現(xiàn)(若其他同學(xué)發(fā)現(xiàn)其他場(chǎng)景也能看到這個(gè),求分享):

# 測(cè)試代碼
class A(object):
    s = 3
# 字節(jié)碼
  2           0 LOAD_CONST               0 ("A")
              3 LOAD_NAME                0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               1 ()
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS
             19 STORE_NAME               1 (A)
             22 LOAD_CONST               2 (None)
             25 RETURN_VALUE

-------------------- 上面 CALL_FUNCTION 執(zhí)行的內(nèi)容如下 -------
  2           0 LOAD_NAME                0 (__name__)
              3 STORE_NAME               1 (__module__)

  3           6 LOAD_CONST               0 (3)
              9 STORE_NAME               2 (s)
             12 LOAD_LOCALS
             13 RETURN_VALUE

這里的 LOAD_NAMESTORE_NAME 打了一套組合拳,把 值 和 符號(hào) 關(guān)聯(lián)了起來(lái),并存到 f->f_locals

那么問(wèn)題來(lái)了:f->f_locals是什么?怎么存?

這里的 f 就是一個(gè)幀對(duì)象,而 f_locals 是它的一個(gè)屬性。而這個(gè)屬性又比較神奇,在幀對(duì)象創(chuàng)建時(shí),會(huì)被置為字典,而在函數(shù)機(jī)制內(nèi),又會(huì)被置為 NULL, 因?yàn)樵诤瘮?shù)機(jī)制內(nèi),就會(huì)用上面那套 fastlocals了。

那么在這里,就會(huì)引出一個(gè)小問(wèn)題,有個(gè)叫 locals() 的函數(shù),來(lái)打印局部變量,這又是怎么回事? 在另一篇文章已經(jīng)談到,歡迎移步: https://segmentfault.com/a/11...

接回上文,既然f->f_locals是字典,那就按照我們理解的字典那樣存就好了唄~

這樣就到了久違的LOAD_LOCALS了,具體實(shí)現(xiàn):

TARGET_NOARG(LOAD_LOCALS)
 {
     if ((x = f->f_locals) != NULL)
     {
         Py_INCREF(x);
         PUSH(x);
         DISPATCH();
     }
     PyErr_SetString(PyExc_SystemError, "no locals");
     break;
 }

很通俗易懂,就是把剛才提到的、存了好多符號(hào)的 字典,拿出來(lái)塞到這個(gè)運(yùn)行時(shí)棧 (下文會(huì)介紹到這個(gè)) 。

塞這個(gè)有啥用呢?這煞費(fèi)苦心的一切,都是為了別人好??!這種種的一切,都是為了 BUILD_CLASS 準(zhǔn)備,因?yàn)樾枰眠@些來(lái)創(chuàng)建類!

那么關(guān)于類的知識(shí),暫告一段落,下回再分解,咱們跑題都快跑出九霄凌外了

那么主角來(lái)了,我們要重點(diǎn)理解這個(gè),因?yàn)檫@個(gè)確實(shí)還挺有意思。

Python 函數(shù)執(zhí)行

Python 函數(shù)的構(gòu)建和運(yùn)行,說(shuō)復(fù)雜不復(fù)雜,說(shuō)簡(jiǎn)單也不簡(jiǎn)單,因?yàn)樗枰獏^(qū)分很多情況,比方說(shuō)需要區(qū)分 函數(shù) 和 方法,再而區(qū)分是有無(wú)參數(shù),有什么參數(shù),有木有變長(zhǎng)參數(shù),有木有關(guān)鍵參數(shù)。

全部展開(kāi)仔細(xì)講是不可能的啦,不過(guò)可以簡(jiǎn)單圖解下大致的流程(忽略參數(shù)變化細(xì)節(jié)):

一路順流而下,直達(dá) fast_function,它在這里的調(diào)用是:

// ceval.c -> call_function

x = fast_function(func, pp_stack, n, na, nk);

參數(shù)解釋下:

func: 傳入的 test;

pp_stack: 近似理解調(diào)用棧 (py方式);

na: 位置參數(shù)個(gè)數(shù);

nk: 關(guān)鍵字個(gè)數(shù);

n = na + 2 * nk;

那么下一步就看看 fast_function 要做什么吧。

初始化一波

定義 co 來(lái)存放 test 對(duì)象里面的 func_code

定義 globals 來(lái)存放 test 對(duì)象里面的 func_globals (字典)

定義 argdefs 來(lái)存放 test 對(duì)象里面的 func_defaults (構(gòu)建函數(shù)時(shí)的關(guān)鍵字參數(shù)默認(rèn)值)

來(lái)個(gè)判斷,如果 argdefs 為空 && 傳入的位置參數(shù)個(gè)數(shù) == 函數(shù)定義時(shí)候的位置形參個(gè)數(shù) && 沒(méi)有傳入關(guān)鍵字參數(shù)

那就

當(dāng)前線程狀態(tài)、co 、globals 來(lái)新建棧對(duì)象 f;

定義fastlocals ( fastlocals = f->f_localsplus; );

把 傳入的參數(shù)全部塞進(jìn)去 fastlocals

那么問(wèn)題來(lái)了,怎么塞?怎么找到傳入了什么鬼參數(shù):這個(gè)問(wèn)題還是只能有 dis 來(lái)解答:

我們知道現(xiàn)在這步是在 CALL_FUNCTION 里面進(jìn)行的,所以塞參數(shù)的動(dòng)作,肯定是在此之前的,所以:

 12          27 LOAD_NAME                2 (test)
             30 LOAD_CONST               4 (3)
             33 CALL_FUNCTION            1
             36 POP_TOP
             37 LOAD_CONST               1 (None)
             40 RETURN_VALUE

CALL_FUNCTION 上面就看到 30 LOAD_CONST 4 (3),有興趣的童鞋可以試下多傳幾個(gè)參數(shù),就會(huì)發(fā)現(xiàn)傳入的參數(shù),是依次通過(guò)LOAD_CONST 這樣的方式加載進(jìn)來(lái),所以如何找參數(shù)的問(wèn)題就變得呼之欲出了;

// fast_function 函數(shù)

fastlocals = f->f_localsplus;
stack = (*pp_stack) - n;

 for (i = 0; i < n; i++) {
     Py_INCREF(*stack);
     fastlocals[i] = *stack++;
 }

這里出現(xiàn)的 n 還記得怎么來(lái)的嗎?回顧上面有個(gè) n = na + 2 * nk; ,能想起什么嗎?

其實(shí)這個(gè)地方就是簡(jiǎn)單的通過(guò)將 pp_stack 偏移 n 字節(jié) 找到一開(kāi)始塞入?yún)?shù)的位置。

那么問(wèn)題來(lái)了,如果 n 是 位置參數(shù)個(gè)數(shù) + 關(guān)鍵字參數(shù),那么 2 * nk 是什么意思?其實(shí)這答案很簡(jiǎn)單,那就是 關(guān)鍵字參數(shù)字節(jié)碼 是屬于帶參數(shù)字節(jié)碼, 是占 2字節(jié)。

到了這里,棧對(duì)象 ff_localsplus 也登上歷史舞臺(tái)了,只是此時(shí)的它,還只是一個(gè)未經(jīng)人事的少年,還需歷練。

做好這些動(dòng)作,終于來(lái)到真正執(zhí)行函數(shù)的地方了: PyEval_EvalFrameEx,在這里,需要先交代下,有個(gè)和 PyEval_EvalFrameEx 很像的,叫 PyEval_EvalCodeEx,雖然長(zhǎng)得像,但是人家干得活更多了。

請(qǐng)看回前面的 fast_function 開(kāi)始那會(huì)有個(gè)判斷,我們上面說(shuō)得是判斷成立的,也就是最簡(jiǎn)單的函數(shù)執(zhí)行情況。如果函數(shù)傳入多了關(guān)鍵字參數(shù)或者其他情況,那就復(fù)雜很多了,此時(shí)就需要由 PyEval_EvalCodeEx 處理一波,再執(zhí)行 PyEval_EvalFrameEx。

PyEval_EvalFrameEx 主要的工作就是解析字節(jié)碼,像剛才的那些 CALL_FUNCTION,LOAD_FAST 等等,都是由它解析和處理的,它的本質(zhì)就是一個(gè)死循環(huán),然后里面有一堆 swith - case,這基本也就是 Python 的運(yùn)行本質(zhì)了。

f_localsplus 存 和 取

講了這么長(zhǎng)的一堆,算是把 Python 最基本的 函數(shù)調(diào)用過(guò)程簡(jiǎn)單掃了個(gè)盲,現(xiàn)在才開(kāi)始探索主題。。

為了簡(jiǎn)單闡述,直接引用名詞:fastlocals, 其中 fastlocals = f->f_localsplus

剛才只是簡(jiǎn)單看到了,Python 會(huì)把傳入的參數(shù),以此塞入 fastlocals 里面去,那么毋庸置疑,傳入的位置參數(shù),必然屬于局部變量了,那么關(guān)鍵字參數(shù)呢?那肯定也是局部變量,因?yàn)樗鼈兌急惶厥鈱?duì)待了嘛。

那么除了函數(shù)參數(shù)之外,必然還有函數(shù)內(nèi)部的賦值咯? 這塊字節(jié)碼也一早在上面給出了:

# CALL_FUNCTION
  5           0 LOAD_CONST               1 ("test")
              3 STORE_FAST               1 (c)

這里出現(xiàn)了新的字節(jié)碼 STORE_FAST,一起來(lái)看看實(shí)現(xiàn)把:

# PyEval_EvalFrameEx 龐大 switch-case 的其中一個(gè)分支:

        PREDICTED_WITH_ARG(STORE_FAST);
        TARGET(STORE_FAST)
        {
            v = POP();
            SETLOCAL(oparg, v);
            FAST_DISPATCH();
        }

# 因?yàn)橛猩婕暗胶?,就順便給出:
#define GETLOCAL(i)     (fastlocals[i])
#define SETLOCAL(i, value)      do { PyObject *tmp = GETLOCAL(i); 
                                     GETLOCAL(i) = value; 
                                     Py_XDECREF(tmp); } while (0)

簡(jiǎn)單解釋就是,將 POP() 獲得的值 v,塞到 fastlocals 的 oparg 位置上。此處,v 是 "test", oparg 就是 1。用圖表示就是:

有童鞋可能會(huì)突然懵了,為什么突然來(lái)了個(gè) b ?我們又需要回到上面看 test 函數(shù)是怎樣定義的:

// 我感覺(jué)往回看的概率超低的,直接給出算了

def test(b):
    c = "test"    
    print b   # 局部變量
    print c   # 局部變量

看到函數(shù)定義其實(shí)都應(yīng)該知道了,因?yàn)?b 是傳的參數(shù)啊,老早就塞進(jìn)去了~

那存儲(chǔ)知道了,那么怎么取呢?同樣也是這段代碼的字節(jié)碼:

22 LOAD_FAST                1 (c)

雖然這個(gè)用腳趾頭想想都知道原理是啥,但公平起見(jiàn)還是給出相應(yīng)的代碼:

# PyEval_EvalFrameEx 龐大 switch-case 的其中一個(gè)分支:
TARGET(LOAD_FAST)
{
    x = GETLOCAL(oparg);
    if (x != NULL) {
        Py_INCREF(x);
        PUSH(x);
        FAST_DISPATCH();
    }
    format_exc_check_arg(PyExc_UnboundLocalError,
        UNBOUNDLOCAL_ERROR_MSG,
        PyTuple_GetItem(co->co_varnames, oparg));
    break;
}

直接用 GETLOCAL 通過(guò)索引在數(shù)組里取值了。

到了這里,應(yīng)該也算是把 f_localsplus 講明白了。這個(gè)地方不難,其實(shí)一般而言是不會(huì)被提及到這個(gè),因?yàn)橐话銇?lái)說(shuō)忽略即可了,但是如果說(shuō)想在性能方面講究點(diǎn),那么這個(gè)小知識(shí)就不得忽視了。

變量使用姿勢(shì)

因?yàn)槭敲嫦驅(qū)ο螅晕覀兌剂?xí)慣了通過(guò) class 的方式,對(duì)于下面的使用方式,也是隨手就來(lái):

class SS(object):
    def __init__(self):
        self.test_dict = {}

    def test(self):
        print self.test_dict

這種方式一般是沒(méi)什么問(wèn)題的,也很規(guī)范。到那時(shí)如果是下面的操作,那就有問(wèn)題了:

class SS(object):
    def __init__(self):
        self.test_dict = {}

    def test(self):
        num = 10
        for i in range(num):
            self.test_dict[i] = i

這段代碼的性能損耗,會(huì)隨著 num 的值增大而增大, 如果下面循環(huán)中還要涉及到更多類屬性的讀取、修改等等,那影響就更大了

這個(gè)類屬性如果換成 全局變量,也會(huì)存在類似的問(wèn)題,只是說(shuō)在操作類屬性會(huì)比操作全局變量要頻繁得多。

我們直接看看兩者的差距有多大把?

import timeit
class SS(object):
    def test(self):
        num = 100
        self.test_dict = {}        # 為了公平,每次執(zhí)行都同樣初始化新的 {}
        for i in range(num):
            self.test_dict[i] = i

    def test_local(self):
        num = 100
        test_dict = {}             # 為了公平,每次執(zhí)行都同樣初始化新的 {}
        for i in range(num):
            test_dict[i] = i
        self.test_dict = test_dict

s = SS()
print timeit.timeit(stmt=s.test_local)
print timeit.timeit(stmt=s.test)

通過(guò)上圖可以看出,隨著 num 的值越大,for 循環(huán)的次數(shù)就越多,那么兩者的差距也就越大了。

那么為什么會(huì)這樣,也是在字節(jié)碼可以看出寫端倪:

// s.test
        >>   28 FOR_ITER                19 (to 50)
             31 STORE_FAST               2 (i)

  8          34 LOAD_FAST                2 (i)
             37 LOAD_FAST                0 (self)
             40 LOAD_ATTR                0 (test_dict)
             43 LOAD_FAST                2 (i)
             46 STORE_SUBSCR
             47 JUMP_ABSOLUTE           28
        >>   50 POP_BLOCK

// s.test_local
        >>   25 FOR_ITER                16 (to 44)
             28 STORE_FAST               3 (i)

 14          31 LOAD_FAST                3 (i)
             34 LOAD_FAST                2 (test_dict)
             37 LOAD_FAST                3 (i)
             40 STORE_SUBSCR
             41 JUMP_ABSOLUTE           25
        >>   44 POP_BLOCK

 15     >>   45 LOAD_FAST                2 (test_dict)
             48 LOAD_FAST                0 (self)
             51 STORE_ATTR               1 (test_dict)

上面兩段就是兩個(gè)方法的 for block 內(nèi)容,大家對(duì)比下就會(huì)知道, s.test 相比于 s.test_local, 多了個(gè) LOAD_ATTR 放在 FOR_ITERPOP_BLOCK 之間。

這說(shuō)明什么呢? 這說(shuō)明,在每次循環(huán)時(shí),s.test 都需要 LOAD_ATTR,很自然的,我們需要看看這個(gè)是干什么的:

TARGET(LOAD_ATTR)
{
     w = GETITEM(names, oparg);
     v = TOP();
     x = PyObject_GetAttr(v, w);
     Py_DECREF(v);
     SET_TOP(x);
     if (x != NULL) DISPATCH();
     break;
 }

# 相關(guān)宏定義
#define GETITEM(v, i) PyTuple_GetItem((v), (i)) 

這里出現(xiàn)了一個(gè)陌生的變量 name, 這是什么?其實(shí)這個(gè)就是每個(gè) codeobject 所維護(hù)的一個(gè) 名字?jǐn)?shù)組,基本上每個(gè)塊所使用到的字符串,都會(huì)在這里面存著,同樣也是有序的:

// PyCodeObject 結(jié)構(gòu)體成員
PyObject *co_names;        /* list of strings (names used) */

那么 LOAD_ATTR 的任務(wù)就很清晰了:先從名字列表里面取出字符串,結(jié)果就是 "hehe", 然后通過(guò) PyObject_GetAttr 去查找,在這里就是在 s 實(shí)例中去查找。

且不說(shuō)查找效率如何,光多了這一步,都能失之毫厘差之千里了,當(dāng)然這是在頻繁操作次數(shù)比較多的情況下。

所以我們?cè)谝恍?huì)頻繁操作 類/實(shí)例屬性 的情況下,應(yīng)該是先把 屬性 取出來(lái)存到 局部變量,然后用 局部變量 來(lái)完成操作。最后視情況把變動(dòng)更新到 屬性 上。

結(jié)語(yǔ)

其實(shí)相比變量,在函數(shù)和方法的使用上面更有學(xué)問(wèn),更值得探索,因?yàn)槟莻€(gè)原理和表面看起來(lái)差別更大,下次有機(jī)會(huì)再探討。平時(shí)工作多注意下,才能使得我們的 PY 能夠稍微快點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)。

歡迎各位大神指點(diǎn)交流, QQ討論群: 258498217
轉(zhuǎn)載請(qǐng)注明來(lái)源: https://segmentfault.com/a/11...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/42334.html

相關(guān)文章

  • 怎么使用python contextvs實(shí)現(xiàn)管理上下文

      python在比較新的版本,3.7這個(gè)版本中,引入了一個(gè)比較新的模塊contextvars,從名字上來(lái)看的話,它是形容為上下變量的,下文就給大家詳細(xì)的解答下,關(guān)于這方面的內(nèi)容?! ython在3.7的時(shí)候引入了一個(gè)模塊:contextvars,從名字上很容易看出它指的是上下文變量(Context Variables),所以在介紹contextvars之前我們需要先了解一下什么是上下文(Con...

    89542767 評(píng)論0 收藏0
  • 處理python遞歸函數(shù)及遞歸算法頻次受限制難題

      本文關(guān)鍵闡述了處理python遞歸函數(shù)及遞歸算法頻次受限制難題,具有非常好的實(shí)用價(jià)值,希望能幫助到大家。如有誤或者未考慮到真正的地區(qū),望鼎力相助  遞歸函數(shù)及遞歸算法頻次受限制  一個(gè)函數(shù)在外部啟用自身,那么這樣的函數(shù)是遞歸函數(shù)。遞歸算法要反復(fù)應(yīng)用自身,每遞歸算法一回,越近最后的值。如果一個(gè)難題需要由很多類似小問(wèn)題處理,可以選擇應(yīng)用遞歸函數(shù)。伴隨著遞歸算法的深層次,難題經(jīng)營(yíng)規(guī)模對(duì)比之前都應(yīng)該所...

    89542767 評(píng)論0 收藏0
  • 淺談reacthooks閉包陷阱

      本文不會(huì)過(guò)多講解基礎(chǔ)知識(shí),更多說(shuō)的是在使用useRef如何能擺脫 這個(gè) 閉包陷阱 ?  react hooks 的閉包陷阱 基本每個(gè)開(kāi)發(fā)員都有遇見(jiàn),這是很令人抓狂的?! ?以下react示范demo,均為react 16.8.3 版本)  列一個(gè)具體的場(chǎng)景:  functionApp(){   const[count,setCount]=useState(1);   useEffect(()=...

    3403771864 評(píng)論0 收藏0
  • Python裝飾器都有什么用呢

      小編寫這篇文章的主要目的,就是給大家介紹關(guān)于python裝飾器的用途方面的知識(shí),這樣對(duì)我們以后的工作也是有一定的幫助,具體用途是什么呢?下面就給各位讀者詳細(xì)的解答下?! ⊙b飾器自身的價(jià)值顯而易見(jiàn),可以加強(qiáng)函數(shù)值基本功能、簡(jiǎn)單化編碼、降低代碼冗余?! ∷氖褂脠?chǎng)景同樣很多,比較簡(jiǎn)單的場(chǎng)景包含打印日志、統(tǒng)計(jì)運(yùn)行時(shí)間,這類例子和用法網(wǎng)上已經(jīng)很多了:  deftime_dec(func):   def...

    89542767 評(píng)論0 收藏0
  • python數(shù)字圖像處理之基本形態(tài)學(xué)濾波

      小編寫這篇文章的主要目的,主要是給大家介紹關(guān)于python數(shù)字圖像處理的一些相關(guān)介紹,包括基本的形態(tài)學(xué)濾波,比如可以使用數(shù)字圖像去進(jìn)行處理類似的形態(tài)學(xué)濾波。那么,具體的內(nèi)容呢?下面就給大家詳細(xì)解答下?! ∫浴 ?duì)圖像進(jìn)行形態(tài)學(xué)變換。變換對(duì)象一般為灰度圖或二值圖,功能函數(shù)放在morphology子模塊內(nèi)?! ?、膨脹(dilation)  原理:一般對(duì)二值圖像進(jìn)行操作。找到像素值為1的點(diǎn),將它...

    89542767 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<