【问题标题】:How to get mutable string?如何获取可变字符串?
【发布时间】:2015-01-18 17:12:49
【问题描述】:

我正在生成 sql 查询并对我的字符串执行大量 += 操作。它看起来像:

insert_string = 'INSERT INTO ' + table_name + ' VALUES '
for row in data_frame.iterrows():
        raw_row = row[1].values
        insert_string += str(tuple(raw_row))

因此,如果我的 insert_string 是不可变的,则每个 += 操作都会创建新字符串。例如,在 C# 中有 StringBuilder 类,它可以初始化具有给定容量的空字符串。我如何在 Python 中做到这一点?

【问题讨论】:

  • 注意 - 你不想采用这种方法......它会受到 SQL 注入攻击。 Python 库有一个标准的 DBI API,允许您安全地构建查询字符串 - 参见 stackoverflow.com/questions/11807601/… 例如

标签: python python-3.x


【解决方案1】:

也许最常见的方法是创建所有片段的列表,并使用str.join 方法将它们连接起来,如下所示:

pieces = ['a', 'b', 'c']
text = ''.join(pieces)
assert text == 'abc'

请注意,您在 分隔符 上调用 join 方法,该分隔符将出现在各个部分之间。在前面的示例中,这是空字符串,但在您的情况下,您实际上可能想要空格甚至换行符之类的东西:

pieces = ['a', 'b', 'c']
text = '\n'.join(pieces)

此外,您可以使用io.StringIO 类获得类似文件的界面:

with io.StringIO() as query_str:
    query_str.write('INSERT INTO ')
    query_str.write(table_name)
    query_str.write(' VALUES ')
    for row in data_frame.iterrows():
        raw_row = row[1].values
        query_str.write(str(tuple(raw_row)))
    # Use query_str.getvalue(), as it will be deleted
    # when the 'with' scope is finished.

【讨论】:

    【解决方案2】:

    这是一篇关于Efficient String Concatenation in Python 的好文章,非常适合您的问题。

    tl;dr:将join 与列表理解一起使用:

    ''.join([str(tuple(row[1].values)) for row in data_frame.iterrows()])
    

    【讨论】:

      【解决方案3】:

      在 Python 2 中,有一个名为 UserString 的模块包含 MutableString

      from UserString import *
      
      myString = MutableString('String')
      myString.pop(0)
      myString[1] = 'h'
      print myString # prints 'thing'
      

      【讨论】:

      • 该类在 2.6 中已弃用,在 3.x 中不存在。有一个关于这个的讨论here
      • 真的,我在2.7.8中使用它。
      • 弃用并不意味着它被删除了,这意味着它不应该在新代码中使用,并且将来可能会被删除。
      【解决方案4】:

      您可能正在寻找的是StringIO,它为字符串列表提供了一个类似文件的接口,并允许您在末尾提取单个字符串:

      import StringIO
      
      builder = StringIO.StringIO()
      builder.write('INSERT INTO ')
      builder.write(table_name)
      builder.write(' VALUES ')
      for row in data_frame.iterrows():
              raw_row = row[1].values
              builder.write(str(tuple(raw_row)))
      insert_string = builder.getvalue()
      

      尽管大多数 python 用户都喜欢直接使用列表,例如Rafael's answer。为了完整起见,您的代码被翻译成该风格:

      builder = ['INSERT INTO ', table_name, ' VALUES ']
      for row in data_frame.iterrows():
              raw_row = row[1].values
              builder.append(str(tuple(raw_row)))
      insert_string = ''.join(builder)
      

      在奇怪的情况下,查看此问题的人实际上需要一个可变字符串;很抱歉,没有什么完全一样的,解决方案在某种程度上取决于您要解决的确切问题。如果你需要一个可变的 byte 字符串,它是可用的,内置的,如bytearray

      >>> b
      bytearray(b'xaby')
      >>> b[1:3] = b'yz'
      >>> b
      bytearray(b'xyzy')
      >>> b.extend(b'foonly')
      >>> b
      bytearray(b'xyzyfoonly')
      

      不过,str 没有等效的操作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多