在Python中如何模擬實現指標

2021-09-27 06:16:30 字數 3961 閱讀 4889

在python中模擬實現指標

因為python中的指標本身不存在,但並不意味著無法使用指標。實際上有多種方法可以在python中模擬指標。

這裡用兩種方法來實現:

使用可變型別作為指標【python中的變數】

使用自定義python物件【python中的物件】

使用可變型別作為指標

您已經了解了可變型別。因為這些物件是可變的,所以您可以將它們視為指向模擬指標行為的指標。假設您要複製以下c**:

void  add_one (int  * x )
此**採用指向整數(*x)的指標,然後將該值遞增1。這是乙個練習**的主要功能:

#include int main(void)
在上面的**中,分配2337給y,列印出當前值,將值遞增1,然後列印出修改後的值。執行此**的輸出如下:

y = 2337 

y = 2338

在python中複製此類行為的一種方法是使用可變型別。考慮使用列表並修改第乙個元素:

>>> def  add_one (x ):

... x [ 0 ] + = 1

...

>>> y = [ 2337 ]

>>> add_one (y )

>>> y [ 0 ]

2338

在這裡,add_one(x)訪問第乙個元素並將其值增加1。使用一種list方法,最終結果似乎已修改了該值。那麼python中的指標確實存在嗎?好吧,這是唯一可能的,因為它list是一種可變型別。如果您嘗試使用a tuple,則會收到錯誤訊息:

>>> z = (2337,)

>>> add_one(z)

traceback (most recent call last):

file "", line 1, in file "", line 2, in add_one

typeerror: 'tuple' object does not support item assignment

上面的**演示了這tuple是不可變的。因此,它不支援專案分配。list不是唯一可變的型別。在python中模仿指標的另一種常見方法是使用a dict。

假設您有乙個應用程式,您希望每次發生有趣事件時都要跟蹤它。實現此目的的一種方法是建立乙個dict並使用其中乙個專案作為計數器:

>>> counters = 

>>> def bar():

... counters["func_calls"] += 1

...>>> def foo():

... counters["func_calls"] += 1

... bar()

...>>> foo()

>>> counters["func_calls"]

2

在此示例中,counters字典用於跟蹤函式呼叫的數量。打**後foo(),計數器已2按預期增加。所有因為dict是可變的。

請記住,這只是模擬指標行為,並不直接對映到c或c ++中的真指標。也就是說,這些操作比在c或c ++中更昂貴。

使用python物件

該dict選項是在python中模擬指標的好方法,但有時記住您使用的金鑰名稱會很繁瑣。如果您在應用程式的各個部分使用字典,則尤其如此。這是自定義python類可以真正幫助的地方。

要構建最後乙個示例,假設您要跟蹤應用程式中的指標。建立乙個類是抽象討厭細節的好方法:

class  metrics (object ):

def __init __ (self ):

self 。_metrics =

此**定義了乙個metrics類。該類仍然使用a dict來儲存實際資料,該資料位於_metrics成員變數中。這將為您提供所需的可變性。現在您只需要能夠訪問這些值。乙個很好的方法是使用屬性:

class metrics(object):

# ...

@property

def func_calls(self):

return self._metrics["func_calls"]

@property

def cat_pictures_served(self):

return self._metrics["cat_pictures_served"]

這段**利用了@property。如果您不熟悉裝飾器,可以在python裝飾器上檢視這個primer。@property這裡的裝飾器允許您訪問func_calls,cat_pictures_served就像它們是屬性一樣:

>>> metrics = metrics()

>>> metrics.func_calls

0>>> metrics.cat_pictures_served

0

您可以將這些名稱作為屬性訪問這一事實意味著您抽象出這些值在a中的事實dict。您還可以更明確地了解屬性的名稱。當然,您需要能夠增加這些值:

class metrics(object):

# ...

def inc_func_calls(self):

self._metrics["func_calls"] += 1

def inc_cat_pics(self):

self._metrics["cat_pictures_served"] += 1

這裡再介紹兩種新方法:

inc_func_calls()

inc_cat_pics()

這些方法會修改指標中的值dict。您現在有乙個類可以修改,就像您正在修改指標一樣:

>>> metrics = metrics()

>>> metrics.inc_func_calls()

>>> metrics.inc_func_calls()

>>> metrics.func_calls

2

在這裡,您可以在應用程式中的各個位置訪問func_calls和呼叫inc_func_calls(),並在python中模擬指標。當您需要在應用程式的各個部分中頻繁使用和更新指標時,這非常有用。

注意:特別是在這個類中,make inc_func_calls()和inc_cat_pics()explicit而不是使用@property.setter阻止使用者將這些值設定為任意int或無效的值,如dict。

class metrics(object):

def __init__(self):

self._metrics =

@property

def func_calls(self):

return self._metrics["func_calls"]

@property

def cat_pictures_served(self):

return self._metrics["cat_pictures_served"]

def inc_func_calls(self):

self._metrics["func_calls"] += 1

def inc_cat_pics(self):

self._metrics["cat_pictures_served"] += 1

在C 中模擬實現boost bind的功能

接觸過boost的c 程式設計的朋友可能對boost bind的印象比較深刻,通過它可以很容易的改變函式的引數個數,實現函式的委託封裝。在非同步程式設計中有著廣泛的應用。在c 中卻沒有提供這一功能,然而,得益於c 強大而靈活的語法機制,我們可以用匿名函式很容易的模擬實現這一過程。首先看一下如下三個函...

模擬實現STL中list容器

mylist.h pragma once include reverseiterator.h templatestruct listnode 鍊錶的節點 假如沒有迭代器,而你又沒有提供print函式 即使提供也不一定能滿足使用者的列印需求 如果使用者想列印鍊錶裡面的資料,就必須知道鍊錶的內部結構 即...

如何模擬實現乙個call apply bind函式

call模擬實現 首先我們實現繫結this功能。比如我們有乙個foo函式 function getname 還有乙個wechat物件 const wechat 我們希望實現 getname.call wechat fedaily以wechat和getname這個為例,這裡的this即getname,...