【问题标题】:Python .join or string concatenationPython .join 或字符串连接
【发布时间】:2011-05-09 04:13:19
【问题描述】:

我意识到,如果您有一个可迭代对象,则应该始终使用 .join(iterable) 而不是 for x in y: str += x。但是,如果只有固定数量的变量不在可迭代对象中,那么使用 .join() 仍然是推荐的方式吗?

例如我有

user = 'username'
host = 'host'

我应该这样做

ret = user + '@' + host

ret = '@'.join([user, host])

从性能的角度来看,我并没有提出太多要求,因为两者都是微不足道的。但是我在这里读到有人说总是使用.join(),我想知道是否有任何特殊原因,或者使用.join() 通常是个好主意。

【问题讨论】:

  • 我一直偏爱'%s@%s' % (user, host)
  • +1 一个有趣的问题,我想知道同样的事情。我通常对这类事情使用格式。

标签: python string-concatenation


【解决方案1】:

如果您要创建这样的字符串,通常需要使用字符串格式:

>>> user = 'username'
>>> host = 'host'
>>> '%s@%s' % (user, host)
'username@host'

Python 2.6 增加了另一种形式,它不依赖于运算符重载,并且有一些额外的特性:

>>> '{0}@{1}'.format(user, host)
'username@host'

作为一般准则,大多数人只会在字符串上添加两个字符串时才使用+。对于更多部分或更复杂的字符串,它们要么使用字符串格式,如上所示,要么将元素组合到列表中并将它们连接在一起(特别是如果涉及任何形式的循环。)使用str.join() 的原因是将字符串添加在一起意味着为每个添加创建一个新字符串(并可能破坏旧字符串)。 Python 有时可以对此进行优化,但str.join() 很快就会变得更清晰、更明显并且速度明显更快。

【讨论】:

  • 值得注意的是,% 表示法已被弃用,.format() 方法是未来之路。相关文档:docs.python.org/library/string.html#formatstrings
  • %-格式化操作尚未弃用。它们被认为是过时的,但它们仍然在所有 Python 版本中可用,尚未安排实际删除,也不会触发任何类型的警告。
  • 顺便说一句,我觉得这有点令人难过,因为字符串格式化作为运算符是最初吸引我进入该语言的可爱 Python 怪癖之一。跨度>
  • 标准字符串格式是通用的,所有程序员都能立即直观地理解这种机制。 Python 的字符串格式是 Python 特有的,没有别的用处;很多人没有立即理解它,不得不经常查看它的文档。我强烈建议使用标准的“传统”字符串格式,除非有特定原因使用 Python 格式。当然,使用它是有原因的,但通常成本不会超过收益,尤其是对于像这样微不足道的常量格式字符串。
  • docs.python.org/library/stdtypes.html: "这种字符串格式化方法是 Python 3.0 中的新标准,应该优先于新代码中字符串格式化操作中描述的 % 格式化。"
【解决方案2】:

我用下一个:

ret = '%s@%s' % (user, host)

【讨论】:

    【解决方案3】:

    (我很确定所有指向字符串格式的人都完全错过了这个问题。)

    通过构造一个数组并加入它来创建一个字符串只是出于性能原因。除非您需要这种性能,或者除非它恰好是实现它的自然方式,否则这样做比简单的字符串连接没有任何好处。

    '@'.join([user, host]) 是不直观的。这让我想知道:他为什么要这样做?有什么微妙之处吗?有没有可能有多个'@'的情况?答案当然是否定的,但得出这个结论比用自然方式编写要花费更多时间。

    不要仅仅为了避免字符串连接而扭曲你的代码;它本质上没有任何问题。加入数组只是一种优化。

    【讨论】:

    • 我不确定我的回答是如何“错过重点”的。另外,“数组”和“列表”不是一回事。
    • @Thomas:几十年来我习惯于调用数组数组,我并不总是努力用 Python 不太常见的名称来调用它们。我认为您的回答没有抓住重点,因为他的问题是专门将[].join 与字符串连接进行比较,并询问是否即使在简单的情况下也要避免字符串连接; 要求以理想的方式来格式化特定的、人为的示例。
    • 问题是关于“固定数量的变量”,这是使用字符串格式(%str.format)的常见情况。我的回答确实解释了为什么人们选择str.join()。至于列表与数组,我不认为使用错误的名称是一个特别好的主意,因为 Python 确实 有数组,而且它们是完全不同的东西。 (出于同样的原因,为了确保读者不会感到困惑,我会注意到[].join 不存在。)
    • @Thomas:问题很明确,无论是在标题:“python .join or string concatination”还是在正文中;他不是在要求第三种选择,而是在问是否有理由更喜欢加入而不是串联。
    • 我通常会使用连接最多三个甚至四个项目,如果这是写我的意思的最清晰的方式。通常它和字符串格式化操作符之间是一个折腾。
    【解决方案4】:

    我认为这个问题的意思是:“这样做可以吗:”

    ret = user + '@' + host
    

    ..答案是肯定的。完全没问题。

    当然,您应该注意可以在 Python 中执行的很酷的格式化操作,并且您应该注意,对于长列表,“加入”是可行的方法,但是对于像这样的简单情况,怎么办?你是完全正确的。简单明了,性能不成问题。

    【讨论】:

      【解决方案5】:

      我只想指出,在我重读 Python 通用风格 PEP PEP-8 Style Guide for Python Code 的一部分之前,我一直倾向于使用就地连接。

      • 代码的编写方式应不损害其他人的利益 Python 的实现(PyPy、Jython、IronPython、Pyrex、Psyco、 等等)。 例如,不要依赖 CPython 的高效实现 a+=b 或 a=a+b 形式的语句的就地字符串连接。 这些语句在 Jython 中运行得更慢。在性能敏感 库的一部分,应该使用 ''.join() 形式。这 将确保串联发生在跨各种线性时间 实现。

      因此,我一直在转换为使用联接的做法,以便在效率特别重要时,我可以保持这种习惯,作为一种更自动的做法。

      所以我会投票给:

      ret = '@'.join([user, host])
      

      【讨论】:

        【解决方案6】:

        我推荐join() over concatenation,基于两个方面:

        1. 更快。
        2. 更优雅。

        关于第一个方面,这里有一个例子:

        import timeit    
        
        s1 = "Flowers"    
        s2 = "of"    
        s3 = "War"    
        
        def join_concat():    
            return s1 + " " + s2 + " " + s3  
        
        def join_builtin():    
            return " ".join((s1, s2, s3))    
        
        print("Join Concatenation: ", timeit.timeit(join_concat))         
        print("Join Builtin:       ", timeit.timeit(join_builtin))
        

        输出:

        $ python3 join_test.py
        Join Concatenation:  0.40386943198973313
        Join Builtin:        0.2666833929979475
        

        考虑到一个庞大的数据集(数百万行)及其处理,每行 130 毫秒,这太多了。

        对于第二个方面,确实更优雅。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-11
          • 1970-01-01
          • 2021-02-24
          • 2016-03-14
          • 2013-03-20
          • 1970-01-01
          • 2021-09-23
          • 1970-01-01
          相关资源
          最近更新 更多