代码之家  ›  专栏  ›  技术社区  ›  Derek Litz

Python字符串连接习惯用法。需要澄清。

  •  4
  • Derek Litz  · 技术社区  · 16 年前

    http://jaynes.colorado.edu/PythonIdioms.html

    “将字符串构建为列表并使用 在分隔符上调用的方法,而不是 字符串连接不带任何字符的片段 分隔符,这是Python的一个怪癖 一开始相当令人惊讶。这是 二次时间而不是线性时间!如果

    错误:对于字符串中的s:result+=s

    右:结果=“”。联接(字符串)”

    Python命令行:

    >>> str1 = 'Not'
    >>> str2 = 'Cool'
    >>> str3 = ''.join([str1, ' ', str2]) #The more efficient way **A**
    >>> print str3
    Not Cool
    >>> str3 = str1 + ' ' + str2 #The bad way **B**
    >>> print str3
    Not Cool
    

    真正的线性时间和 B

    5 回复  |  直到 6 年前
        1
  •  14
  •   Mark Byers    16 年前

    对对于您选择的示例,重要性并不清楚,因为您只有两个非常短的字符串,因此追加可能会更快。

    a + b 对于Python中的字符串,它会导致新的分配,然后将a和b中的所有字节复制到新字符串中。如果在一个包含大量字符串的循环中执行此操作,则必须一次又一次地复制这些字节,而且每次必须复制的字节数都会变长。这给出了二次行为。

    另一方面,创建字符串列表并不复制字符串的内容,它只是复制引用。这是难以置信的快,并在线性时间运行。然后,join方法只进行一次内存分配,并且只将每个字符串复制到正确的位置一次。这也只需要线性时间。

    ''.join

    如果您需要更具说服力的内容,请亲自尝试使用10个字符创建一个字符串:

    >>> chars = ['a'] * 10000000
    >>> r = ''
    >>> for c in chars: r += c
    >>> print len(r)
    

    与之相比:

    >>> chars = ['a'] * 10000000
    >>> r = ''.join(chars)
    >>> print len(r)
    

    第一种方法大约需要10秒钟。秒不到1秒。

        2
  •  6
  •   jason    16 年前

    Schlemiel the Painter's Algorithm (请注意,一些实现将对此进行优化,使其不是二次的)。 join

        3
  •  4
  •   Dustin Getz sunsations    16 年前

    当你编码的时候 s1 + s2 ,Python需要分配一个新的字符串对象,复制 s1 进入它,然后在那之后所有的字符 s2 . 这个琐碎的操作不承担二次时间成本:成本是 O(len(s1) + len(s2))

    但是,考虑一下你给出的报价中的代码: for s in strings: result += s .

    每一次 一个新的 s 增加了,, 所有以前的 必须首先复制到新分配的空间中 result (字符串是不可变的,因此必须进行新的分配和复制)。假设有N个长度为L的字符串:第一次复制L个字符,第二次复制2*L,第三次复制3*L。。。总之,就是这样 L * N * (N+1) / 2 正在复制角色。。。所以,是的,它是N的平方。

        4
  •  1
  •   Dustin Getz sunsations    16 年前
        5
  •  0
  •   ilya n.    16 年前

    如果你指的是与其他人相同的东西,这并不明显。当您拥有 比如说字符串 M 长度

    A.

    x = ''.join(strings) # Takes M*N operations 
    

    B

    x = ''
    for s in strings:
        x = x + s  # Takes N + 2*N + ... + M*N operations
    

    除非通过实施进行优化,否则是的, 在总长度上是线性的 T = M*N B T*T / N M >> N .

    join :当你说“我有一些字符串”时,通常可以通过说你有一个 返回字符串。现在,这正是你要传递的 "string".join()