在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,...