2014-02-09 53 views
5

在此處發表評論:How to define a new string formatter,我嘗試了子類string.Formatter。這是我所做的。不幸的是我似乎已經打破它在這個過程中subclass string.Formatter

import string 
from math import floor, log10 

class CustFormatter(string.Formatter): 
    "Defines special formatting" 
    def __init__(self): 
     super(CustFormatter, self).__init__() 

    def powerise10(self, x): 
     if x == 0: return 0, 0 
     Neg = x < 0 
     if Neg: x = -x 
     a = 1.0 * x/10**(floor(log10(x))) 
     b = int(floor(log10(x))) 
     if Neg: a = -a 
     return a, b 

    def eng(self, x): 
     a, b = self.powerise10(x) 
     if -3 < b < 3: return "%.4g" % x 
     a = a * 10**(b%3) 
     b = b - b%3 
     return "%.4g*10^%s" % (a, b) 

    def format_field(self, value, format_string): 
     # handle an invalid format 
     if format_string == "i": 
      return self.eng(value) 
     else: 
      return super(CustFormatter,self).format_field(value, format_string) 

fmt = CustFormatter() 
print('{}'.format(0.055412)) 
print(fmt.format("{0:i} ", 55654654231654)) 
print(fmt.format("{} ", 0.00254641)) 

彷彿在最後一行,我不按位置參考變量,我得到一個KeyError。顯然,我們期望在原始課程中有一個可選的鍵,但我不明白爲什麼,我不知道我做錯了什麼。

回答

4

str.formatdoes auto numbering,而string.Formatter沒有。

修改__init__和覆蓋get_value將做的伎倆。

def __init__(self): 
    super(CustFormatter, self).__init__() 
    self.last_number = 0 

def get_value(self, key, args, kwargs): 
    if key == '': 
     key = self.last_number 
     self.last_number += 1 
    return super(CustFormatter, self).get_value(key, args, kwargs) 

順便說一句,以上代碼並不嚴格模仿str.format的行爲。 str.format抱怨,如果我們混合自動編號與手動編號,但上面沒有。

>>> '{} {1}'.format(1, 2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: cannot switch from automatic field numbering to manual field specification 
>>> '{0} {}'.format(1, 2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: cannot switch from manual field specification to automatic field numbering 
1

好消息:你沒有做錯任何事。 壞消息:這就是string.Formatter的行爲,它不支持{}類似位置格式。所以,即使沒有任何子類化,最後的調用也會失敗。好消息:這是可以通過重寫parse方法是固定的:

import string 

class CF(string.Formatter): 
    def parse(self, s): 
     position = 0 
     for lit, name, spec, conv in super(CF, self).parse(s): 
      if not name: 
       name = str(position) 
       position += 1 
      yield lit, name, spec, conv 

壞消息......啊,不是,這基本上是:

>>> CF().format('{} {}!', 'Hello', 'world') 
'Hello world!' 
+0

謝謝你,你知道什麼是+和 - 由前面的海報提供的重寫分析或get_value?還是相當於? – Cambium

+0

@Cambium falsetru的版本對我來說看起來更易讀,此外,您需要更少地重寫一個方法(儘管必須重寫構造函數並引入一個屬性)。他對混合樣式的讚揚也適用於我的代碼(但是,您可以擴展任一版本以修復該問題)。 – bereal

相關問題