代码之家  ›  专栏  ›  技术社区  ›  Evan Fosmark

Python连接:为什么是string.join(list)而不是list.join(string)?

  •  1514
  • Evan Fosmark  · 技术社区  · 16 年前

    这一直让我困惑。看起来这样会更好:

    my_list = ["Hello", "world"]
    print(my_list.join("-"))
    # Produce: "Hello-world"
    

    my_list = ["Hello", "world"]
    print("-".join(my_list))
    # Produce: "Hello-world"
    

    有没有具体的原因呢?

    9 回复  |  直到 5 年前
        1
  •  1346
  •   Boris Verkhovskiy Brian Clapper    4 年前

    这是因为任何iterable都可以连接(例如,list、tuple、dict、set),但它的内容和“joiner” 必须是 串。

    '_'.join(['welcome', 'to', 'stack', 'overflow'])
    '_'.join(('welcome', 'to', 'stack', 'overflow'))
    
    'welcome_to_stack_overflow'
    

    TypeError: sequence item 0: expected str instance, int found
    
        2
  •  370
  •   Yoshiki Shibukawa    3 年前

    会议讨论了这一点 String methods... finally 线程,并被Guido接受。这条线索始于1999年6月 str.join 包含在2000年9月发布的Python 1.6中(支持Unicode)。Python 2.0(受支持 str 方法包括 join )于2000年10月发布。

    • 本线程中提出了四个选项:
      • str.join(seq)
      • seq.join(str)
      • seq.reduce(str)
      • 参加 作为内置函数
    • list s和 tuple s、 但是所有的序列/片段。
    • 序号减少(str) 这对新手来说很难。
    • 将序列引入到str/unicode的意外依赖项。
    • join() 因为内置函数只支持特定的数据类型。因此,使用内置名称空间并不好。如果 __add__ 方法,那么它就会 O(n²) .
    • 分隔符字符串( sep

    以下是一些额外的想法(我自己和我朋友的):

    • Unicode支持即将到来,但它不是最终的。当时,UTF-8最有可能取代UCS2/4。要计算UTF-8字符串的总缓冲区长度,需要知道字符编码规则。
    • 当时,Python已经决定了一个通用的序列接口规则,用户可以在其中创建一个类似序列(iterable)的类。但是Python直到2.2才支持扩展内置类型。当时很难提供基本服务 iterable 类(另一个注释中提到)。

    Guido的决定记录在 historical mail ,决定 str.join(seq) :


    吉多·范罗苏姆

        3
  •  255
  •   Community Dunja Lalic    4 年前

    因为 join()

    我同意这看起来很有趣。

    http://www.faqs.org/docs/diveintopython/odbchelper_join.html :

    当我第一次学习 Python,我希望join是一种方法 分隔符作为参数。许多 人们也有同样的感受 join方法背后的故事。先前的 这些方法很有用。有一个 所有字符串函数;每个 论点这些职能被视为 重要到可以放在 字符串本身,这是有意义的 用于下、上、下等功能 分裂但许多核心Python 方法,认为它应该是一个 根本不应该动,只是呆着 旧字符串模块的一部分(其中 但您也会看到编写的代码 可以使用旧的string.join函数 相反

    ---马克·朝圣者,潜入巨蟒

        4
  •  75
  •   Kiv    16 年前

    • 它也必须适用于不同的iterables(元组、生成器等)
    • 它在不同类型的字符串之间必须具有不同的行为。

    >>> b"".join
    <built-in method join of bytes object at 0x00A46800>
    >>> "".join
    <built-in method join of str object at 0x00A28D40>
    

    如果join是列表的一个方法,那么它必须检查它的参数以决定调用哪一个参数。你不能把byte和str连接在一起,所以他们现在的方式是有意义的。

        5
  •  47
  •   Aaron Hall    8 年前

    为什么 string.join(list) 而不是 list.join(string)

    这是因为 join 是一个“字符串”方法!它从任何iterable创建一个字符串。如果我们把方法放在列表上,那么当我们有一个不是列表的iterables时呢?

    如果你有一组字符串呢?如果这是一个 list 列表 在您可以将元素加入单个字符串之前!例如:

    some_strings = ('foo', 'bar', 'baz')
    

    class OurList(list): 
        def join(self, s):
            return s.join(self)
    

    要使用它,请注意,我们必须首先从每个iterable创建一个列表,以连接该iterable中的字符串,从而浪费内存和处理能力:

    >>> l = OurList(some_strings) # step 1, create our list
    >>> l.join(', ') # step 2, use our list join method!
    'foo, bar, baz'
    

    因此,我们必须添加一个额外的步骤来使用list方法,而不仅仅是使用内置的string方法:

    >>> ' | '.join(some_strings) # a single step!
    'foo | bar | baz'
    

    Python用于创建最终字符串的算法 str.join

    因此,虽然传递生成器通常比列表理解更好, str.join 这是一个例外:

    >>> import timeit
    >>> min(timeit.repeat(lambda: ''.join(str(i) for i in range(10) if i)))
    3.839168446022086
    >>> min(timeit.repeat(lambda: ''.join([str(i) for i in range(10) if i])))
    3.339879313018173
    

    str.join 操作在语义上仍然是一个“字符串”操作,因此将其置于 str 对象,而不是其他可重用对象。

        6
  •  24
  •   Andy Dent    15 年前

    我理解为什么它适用于任何可移植的东西,所以不容易实现 只是 在名单上。

        7
  •  14
  •   Iulian Onofrei Denis Oliveira    4 年前

    - 在里面 "-".join(my_list) 声明您正在从将元素连接到列表转换为字符串。它是面向结果的。(只是为了便于记忆和理解)

    我做了一份详尽的方法的备忘单供你参考。

    string_methods_44 = {
        'convert': ['join','split', 'rsplit','splitlines', 'partition', 'rpartition'],
        'edit': ['replace', 'lstrip', 'rstrip', 'strip'],
        'search': ['endswith', 'startswith', 'count', 'index', 'find','rindex', 'rfind',],
        'condition': ['isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isnumeric','isidentifier',
                      'islower','istitle', 'isupper','isprintable', 'isspace', ],
        'text': ['lower', 'upper', 'capitalize', 'title', 'swapcase',
                 'center', 'ljust', 'rjust', 'zfill', 'expandtabs','casefold'],
        'encode': ['translate', 'maketrans', 'encode'],
        'format': ['format', 'format_map']}
    
        8
  •  13
  •   S.Lott    16 年前

    主要是因为 someString.join() 这是一根绳子。

        9
  •  2
  •   Dmytro    6 年前

    两者都不好。

    join(定界)有点好,因为我们已经习惯了字符串是一种基本类型(从语言上讲,它们是)。然而,这意味着连接需要动态调度,因为在 a.split("\n") python编译器可能不知道a是什么,需要查找它(类似于vtable查找),如果您经常这样做的话,这是非常昂贵的。

    如果python运行时编译器知道list是一个内置模块,它可以跳过动态查找并直接将意图编码到字节码中,否则它需要动态解析“a”的“join”,这可能是每个调用的多个继承层(因为在调用之间,join的含义可能已经改变,因为python是一种动态语言)。

    可悲的是,这是抽象的终极缺陷;不管你选择什么抽象,你的抽象只会在你试图解决的问题的背景下才有意义,因此,当你开始将它们粘在一起,而不将它们包装在与你的意识形态一致的视图中时,你永远不可能有一个不与潜在意识形态不一致的一致的抽象。知道了这一点,python的方法更加灵活,因为它更便宜,这取决于您是否需要支付更多的费用来让它看起来“更好”,或者是通过制作您自己的包装器,或者是您自己的预处理器。

        10
  •  1
  •   fiftytwocards    5 年前

    my_list "-" 两者都是对象。具体来说,它们是类的实例 list str join 函数属于类 . 因此,语法 "-".join(my_list) "-" 正在 我的清单