【问题标题】:string_builder decorator in python 2.7 - how to do it and should I?python 2.7 中的 string_builder 装饰器 - 我应该怎么做?
【发布时间】:2012-10-17 05:52:00
【问题描述】:

因此,Python 没有提供明确的 C# 或 Java 风格的 StringBuilder 类。 请注意,我对 Python 有点陌生,所以我不确定我的想法是否好。

假设我想要一个装饰器(如果可能的话)将可迭代对象连接在一起。这个特定的例子可以用不同的方式实现,但我可以想到其他用例。所以...

@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 ';'

再次,我知道有其他方法可以做到这一点。然而,这能做到吗?装饰器可以始终尊重原始函数的签名,还是有时或根本不尊重?如果这是可能的,那么它是异端吗?为什么?

【问题讨论】:

  • 它不是称为 StringBuilder,但您可以使用cStringIO.StringIO 类,或者在Python 3 上使用io.StringIO 类。此外,在 Python 上构建简单的字符串实际上非常快。
  • @DietrichEpp StringIO 为此目的相当不方便,因为它的目的是作为模拟文件,而不是作为“字符串生成器”。上次我检查它时重复获取值时速度出奇的慢(比包含字符串列表和str.join的手写对象慢几倍)。
  • @delnan:您能描述一下“模拟文件”和“字符串生成器”有何不同吗?你确定你说的是cStringIO?此外,由于 OP 不会多次获得该值,因此在这种情况下的性能是无关紧要的。
  • 我不能说这是否是好的做法,但它很聪明,我可以看到它很方便。

标签: python python-2.7 decorator stringbuilder


【解决方案1】:

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 +
                ';')
    

【讨论】:

  • 老实说,我发现我开始做一些奇怪的事情,比如缩短变量名、引入额外的变量和以不同的方式格式化字符串,所有这些都是因为我必须适应每行 80 个字符限制:(同样,这可能源于缺乏经验,但不得不担心线路的长度目前正在降低我的生活质量。
  • 字符限制始终是软限制。如果您不能在不损害代码及其可读性的情况下遵循它,请不要这样做。顺便说一句,您可以使用反斜杠字符在 Python 中换行。话虽这么说,我真的不明白这与这个问题有什么关系。你想要那个装饰器的原因是你想要多行吗?你总是可以建立一个列表并最终加入。
猜你喜欢
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2015-10-18
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多