2012-10-26 27 views
2

因此,Python沒有提供明確的C#或Java風格的StringBuilder類。 請注意,我對Python有點新,所以我不確定我的想法是否合適。python 2.7中的string_builder裝飾器 - 如何做到這一點,我應該?

假設我想要一個裝飾器(如果可能的話),它將迭代器連接在一起。這個特殊的例子可以以不同的方式實現,但我可以考慮其他用例。所以...

@string_builder 
def build_insert_statement(table_name, col_names, values, where_clause): 
    yield 'insert into ' 
    yield table_name 
    yield ' (' 
    yield ', '.join(col_names) 
    yield ') values (' 
    yield ', '.join(values) 
    yield ') where ' 
    yield where_clause 
    yield ';' 

同樣,我知道有其他的方法可以做到這一點。但是,這可以做到嗎?裝飾者是否可以始終尊重原始功能的簽名,或者只是有時或根本不遵守?如果這是可能的,那麼這是異端嗎?爲什麼?

+1

它不叫* * StringBuilder,但是你可以使用'cStringIO.StringIO'類,或者在Python 3上使用'io.StringIO'類。而且,在Python上構建天真的字符串實際上相當快。 –

+0

@DietrichEpp'StringIO'爲此目的相當不方便,因爲它的目的是模擬文件,而不是「字符串生成器」。上次我檢查它的速度驚人地慢(比手寫對象包裝一串字符串和'str.join'慢幾倍),當重複獲取該值時。 – delnan

+0

@delnan:你能描述一個「模擬文件」和「字符串生成器」會有什麼不同嗎?你確定你在談論'cStringIO'嗎?而且,由於OP不會超過一次,所以在這種情況下的性能是無關緊要的。 –

回答

2

string_builder下面的定義應該工作:

from functools import wraps 

def string_builder(func): 
    @wraps(func) 
    def wrapped(*args, **kwargs): 
     return ''.join(func(*args, **kwargs)) 
    return wrapped 

使用在你的問題中定義的函數string_builder作爲裝飾:

>>> build_insert_statement('foo', ['bar'], ['1'], 'baz') 
'insert into foo (bar) values (1) where baz;' 

注意,使用[functools.wraps] [1]是不是必要的,但這是一個好習慣,因爲如果沒有它,修飾後的功能名稱(build_insert_statement.__name__)將被「包裹」而不是「build_insert_statement」。

所以這是可能的,這是一個好主意嗎?

不是你的例子,但你說你有其他用例。像這樣的裝飾器不是異端邪說,但你不應該過度使用裝飾器,因爲它可能會掩蓋實現。

如果你只是擔心線長,請考慮以下選項之一:

  • 名單上使用''.join()

    def build_insert_statement(table_name, col_names, values, where_clause): 
        return ''.join(['insert into ', 
            table_name, 
            ' (', 
            ', '.join(col_names), 
            ') values (', 
            ', '.join(values), 
            ') where ', 
            where_clause, 
            ';']) 
    
  • +結合的字符串:

    def build_insert_statement(table_name, col_names, values, where_clause): 
        return ('insert into ' + 
          table_name + 
          ' (' + 
          ', '.join(col_names) + 
          ') values (' + 
          ', '.join(values) + 
          ') where ' + 
          where_clause + 
          ';') 
    
+1

你可能也想通過kwargs ... – Amber

+0

說實話,我發現我開始做怪異的事情,如縮短變量名稱,並以不同的方式引入額外的變量和格式化字符串,因爲我必須適應每行80個字符限制:(再次,這可能源於缺乏經驗,但不必擔心線路的長度正在降低我的生活質量。 –

+1

字符限制始終是一個軟限制,如果在不傷害代碼及其可讀性的情況下無法遵循它,請勿這樣做,並且順便說一句,你可以使用反斜線字符在Python中包裝線條,也就是說,我並沒有真正理解這個問題是如何與問題相關的。 ?你總是可以建立一個列表並最終加入。 – poke