2013-10-23 25 views
8

我通常使用下面的圖案(如this question提到):縮寫形式的String.Format(...,**當地人())

a=1 
s= "{a}".format(**locals()) 

我認爲這是寫易於閱讀的好方法碼。

有時它以「鏈」串格式是有用的,以「模塊化」複雜的字符串創建:

a="1" 
b="2" 
c="{a}+{b}".format(**locals()) 
d="{c} is a sum".format(**locals()) 
#d=="1+2 is a sum" 

很快,代碼糾纏與X.format(**locals())。 爲了解決這個問題,我試圖創建一個lambda:

f= lambda x: x.format(**locals()) 
a="1" 
b="2" 
c= f("{a}+{b}") 
d= f("{c} is a sum") 

但這拋出一個KeyError異常,因爲locals()是拉姆達的當地人。

我也試圖應用的格式只在最後一個字符串:

a="1" 
b="2" 
c="{a}+{b}" 
d="{c} is a sum".format(**locals()) 
#d=="{a}+{b} is a sum" 

但是,這並不工作,因爲只有蟒格式一次。 現在,我可以寫反覆格式化,直到有什麼更多的做一個功能:

def my_format(string, vars): 
    f= string.format(**vars) 
    return f if f==string else my_format(f, vars) 

但我想知道:有沒有更好的方式來做到這一點?

回答

4

f = lambda x, l=locals(): x.format(**l)的工作原理。

,如果你想要一個版本,是一個小更包羅萬象(也可能是慢了很多):

fg = lambda x, l=locals(), g=globals(): x.format(**dict(g.items() + l.items())) 

會發現無論是符號當地人或全局。

+0

你可能希望當地人重寫全局變量。目前,你反其道而行之,因爲後來的辯論贏得勝利。 – Collin

+0

好點...我會做出改變。 –

0

這不是一個班輪,但它的工作原理:

def fmt(s, l=locals()): 
    while '{' in s: 
     s = s.format(**l) 
    return s 

a="1" 
b="2" 
c="{a}+{b}" 
d="{c} is a sum" 

print fmt(d) # 1+2 is a sum 

這裏有一個行(略效率較低)遞歸版本:

fmt = lambda s, l=locals(): fmt(s.format(**l), l=l) if '{' in s else s 
2

如果你只需要內做到這一點功能範圍作爲本地快捷方式,以下將起作用:

def formatter(fmt, loc=locals()): 
    return fmt.format(**loc) 

但是,這將綁定值ret在函數聲明的時候由locals()所調用,而不是執行,所以它不會隨着值的變化而更新,從其他任何範圍調用時也不會有用。

如果你想獲得訪問調用方法的locals,你需要inspect調用堆棧(http://docs.python.org/2/library/inspect.html

import inspect 

def formatter(fmt): 
    parent = inspect.stack()[1][0] # 1 = the previous frame context 
            # 0 = the frame object 
    return fmt.format(**parent.f_locals) 

注意,這可能不是對於不CPython的蟒蛇的實施工作。

現在你可以這樣做:

a = "1" 
b = "2" 
c = formatter("{a}+{b}") 
d = formatter("{c} is a sum") 
+0

實際上,有時候這是真的,但並不總是......它看起來像locals()實際上返回了一個指向'locals'字典值的指針,這似乎改變了。你可以做下面的實驗:'f = locals(); x = 1; g =當地人(); f == g',即使你已經修改了f和g之間的局部值,它也是真的。另外:'def fn(x,l = locals()):print l [x]; x = 2; FN( 'X'); x = 3; fn('x')'會打印2,然後是3.有時候它應該是真的,所以這是一個很好的評論,但似乎有很多實際情況可以忽略它。 –