我試圖從同一行識別來電者。下面是一個例子:如何從被調用者的同一行中識別多個呼叫者?
def get_file():
caller_id = get_caller_id()
return open(caller_id, 'a+')
def write_content():
with get_file() as f1, get_file() as f2: # line with multiple callers
f1.write('123')
f2.write('456')
def fun():
write_content()
write_content()
write_content()
write_content()
write_content()
功能get_caller_id()
是我想要的。這會產生兩個不同的id
S爲第一和功能write_content()
第二get_file()
電話,但所有的功能fun()
5個通話write_content()
,兩個get_file()
通話將返回這5個write_content()
電話中同一個文件的對象。
調用fun()
後,只會生成兩個文件,一個文件內容爲「123123123123123」,另一個文件爲「456456456456456」。返回的caller_id
只能對當前正在運行的會話保持一致,並且在重新啓動python內核之後caller_id
是否不一致無關緊要。
我已經試過inspect
模塊:
def get_caller_id():
cur_frame = inspect.currentframe()
caller_frame = inspect.getouterframes(cur_frame)[2]
frame_obj = caller_frame[0]
line_no = caller_frame[2]
return '{}_{}'.format(id(frame_obj), line_no)
當只有一個get_file()
在一條線上通話,這get_caller_id()
效果很好。但是對於來自同一行的多個呼叫者,它將生成相同的ID,這不是我想要的。
我已經搜索瞭如何在一行中獲取調用者的列位置,但什麼都沒找到。這種定位可能嗎?
謝謝。
編輯:
下面實際上是我在做什麼:
class AutoSharedParams(object):
def __init__(self, dict_key='root', params_dict=None, init_value=None):
if params_dict is None:
params_dict = {}
self._params_dict = params_dict
self._dict_key = dict_key
if self._dict_key not in self._params_dict and init_value is not None:
self.x = init_value
def __call__(self, init_value=None, func=None):
caller_frame = inspect.getouterframes(inspect.currentframe())[1]
caller_id = id(caller_frame[0])
caller_ln = caller_frame[2]
key = '{}_c{}_l{}'.format(self._dict_key, caller_id, caller_ln)
if key not in self._params_dict:
if func:
init_value = func()
else:
init_value = None
return AutoSharedParams(dict_key=key, params_dict=self._params_dict, init_value=init_value)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return False
@property
def x(self):
if self._dict_key in self._params_dict:
return self._params_dict[self._dict_key]
else:
return None
@x.setter
def x(self, value):
self._params_dict[self._dict_key] = value
我用lasagne
創建細胞神經網絡(asp
是一個實例,如果AutoSharedParams
):
with asp(func=lambda: lasagne.init.HeNormal(gain='relu')) as w:
l = Conv2DLayer(l, num_filters=16, filter_size=(3, 3), W=w.x)
w.x = l.W
with asp(init_value=0) as w, asp(init_value=0) as b: # there are two calls in one line
l = Conv2DLayer(l, num_filters=16, filter_size=(3, 3), W=w.x, b=b.x)
w.x = l.W
b.x = l.b
我有很多類似但不同的代碼,如上所述,我想分享這些cre (w.x
,b.x
和許多其他),當這段代碼再次通過。最簡單的方法是list.append(w)
和w=list.pop(0)
,但是如果代碼中有不同的路徑,它將不兼容。所以我需要一個鍵來標記它們。
你究竟在試圖用這個做些什麼?爲什麼功能會根據調用函數的不同而有所不同,並且這不會使測試更加或者更不可能? – jonrsharpe
@jonrsharpe我實際上在許多不同的地方創建了許多對象,並希望它們在下次調用該函數時自動存儲和共享。這些變量保存到字典中並從字典中恢復,並且此字典中使用的密鑰是調用的「caller_id」,它將創建相應的變量。當然,我可以手動爲每個變量分配一個鍵,但這會是多餘的,我不能保證鍵不會被重複。 – Texot
您是否考慮過使用裝飾器將它們附加到調用者?你可以舉一個更清晰的例子,因爲我懷疑是XY問題。 – jonrsharpe