2012-03-06 61 views
2

是否可以編寫一個函數f是採用混合數據的任意元組:的Python:函數返回一個字典的鍵是輸入參數的名字

T = 1.0 
N = 20 
L = 10 
args = (T,N,L) 

f(*args) # or maybe f(T,N,L)? 

,並返回作爲輸出:

{'T':1.0, 'N':20, 'L':10} 

有一個related question使用local,但我似乎失去了名字,一旦他們傳遞給函數。有沒有辦法來防止這種情況?我猜測這些變量是按值傳遞的,因此它們被認爲是新的對象。

跟帖:Python: Using a dummy class to pass variable names?

+1

你似乎在這裏混淆概念。其他語言有變量,但[Python有名稱](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#python-has-names)。 – 2012-03-06 15:14:14

+0

可能不可能,但我會留下這個作爲一個評論,當我無法證實錯誤(可能與字節碼分析或一些這樣的愚蠢)。 – SingleNegationElimination 2012-03-06 15:14:21

+0

我認爲可能有一些限制,請參閱我的答案。雖然不健壯或值得稱道。確切地說, – 2012-03-06 15:26:28

回答

3

沒有,這是不可能的,一般與*args。你將不得不使用關鍵字參數:

>>> def f(**kwargs): 
... return kwargs 
... 
>>> f(T=1.0, N=20, L=10) 
{'T': 1.0, 'L': 10, 'N': 20} 

的原因是,*args不引入對個人參數名稱;它只爲其整個列表引入名稱args。該函數沒有洞察到如何命名,如果有的話,參數在它之外。

當自變量的數量是固定的,你可以用locals做到這一點:(或者明確地return {'T': T, 'N': N, 'L': L}

>>> def g(T, N, L): 
... return locals() 
... 
>>> g(T=1.0, N=20, L=10) 
{'L': 10, 'T': 1.0, 'N': 20} 

+0

。然後你回來明確地描述關鍵字名稱,而不是在你做'(T = 1.0,N = 20,L = 10)'時隱含地派生它們。 – 2012-03-06 15:15:55

2

在Python變量只是標籤附加到值。因此,從另一個範圍無法知道調用函數時使用的標籤。

0

是的,據我所知,args是一個列表。爲了保留標籤名稱,您需要將一個字典傳遞給** kwargs,並使用local明確或程序化地設置名稱。

你可以這樣做:

def filter_locals(caller_locals, *args): 
    filtered = {} 
    for key in args: 
     filtered[key] = caller_locals[key] 
    return filtered 

然後:

X = 1 
Y = 2 
func(filter_locals(locals(), 'X', 'Y') 

凡FUNC處理任意長度列表,kwargs。

0

這將會是必要通過作爲獨立參數:

keys = ('T', 'N', 'L') 
values = (1.0, 20, 10) 
d = dict(zip(keys, values)) 

在你的代碼中,行args = (T,N,L)計算結果爲args = (1.0, 20, 10),該變量的T「名」 ,N,L被它們的值替換。

2

你的猜測是錯誤的不幸,而事實上整個問題暴露出的Python的名字是如何工作的一種誤解。

Python對象大體上不知道它們的名字。當您考慮到您可以輕鬆地分配a=b,並且現在ab都指向完全相同的對象時,這是完全可以理解的。Python的「變量」只是指向對象的名稱,它們並不以任何真實的方式包含這些對象。將參數傳遞給函數時,您傳遞的是底層對象,而不是名稱。接收函數簡單地將它們綁定到函數簽名中指定的名稱上 - 或者,在您的情況下,只需將它們保留在args中,而不給它們任何名稱。

因此,當您詢問如何獲取對象在不同範圍內的名稱時,您無法自行詢問對象。可能有辦法做到這一點,但它涉及到檢查呼叫幀,我非常懷疑你想要。

1

使用globals()的解決方案。這如果是在模塊範圍內是唯一隻會工作,所以它的脆弱 - 如果有重複,它首先會選擇指向該值,有些武斷。是的,你最好不要這樣做,而是反思問題。

def f(*names): 
    r = {} 
    for n in names: 
     r[[ name for name in globals() if globals()[name] is n ][0]] = n 
    return r 

T = 1.0 
N = 20 
L = 10 

print f(T,N,L) 
{'T': 1.0, 'L': 10, 'N': 20} 
相關問題