list選取 - python3 join




Python連接:為什麼它是string.join(list)而不是list.join(string)? (6)

這一直困擾著我。 看起來這樣會更好:

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

比這個:

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

有沒有特定的原因是這樣的?


為什麼它是string.join(list)而不是list.join(string)

這是因為join是一個“字符串”方法! 它從任何迭代中創建一個字符串。 如果我們將這種方法固定在列表上,那麼當我們有不是列表的迭代器時呢?

如果你有一串字符串呢? 如果這是一個list方法,那麼在將這些元素連接到單個字符串之前,您必須將每個這樣的字符串迭代器都作為list進行投射! 例如:

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

讓我們滾動我們自己的列表連接方法:

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

要使用它,請注意,我們必須首先從每個迭代中創建一個列表,以便在迭代中加入字符串,同時浪費內存和處理能力:

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

所以我們看到我們不得不添加一個額外的步驟來使用我們的list方法,而不是使用內建的字符串方法:

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

發電機性能警告

Python用於用str.join創建最終字符串的str.join實際上必須經過兩次迭代,所以如果你提供了一個生成器表達式,它必須首先將它物化為列表,然後才能創建最終字符串。

因此,在傳遞生成器時通常比列表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對像上使用str.join操作比在其他iterables上操作仍然有意義。


-聲明你正在加入一個列表並轉換成一個字符串。它是以結果為導向的(只是為了便於記憶和理解)

我製作了一個詳盡的methods_of_string作為參考。

string_methonds_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']}

因為join()方法在字符串類中,而不是列表類?

我同意它看起來很有趣。

請參閱http://www.faqs.org/docs/diveintopython/odbchelper_join.html

歷史筆記。 當我第一次學習Python時,我期望join是一個列表的方法,它將分隔符作為參數。 很多人都有同樣的感受,並且在連接方法背後有一個故事。 在Python 1.6之前,字符串沒有所有這些有用的方法。 有一個單獨的字符串模塊,其中包含所有的字符串函數; 每個函數都將一個字符串作為其第一個參數。 這些函數被認為足夠重要,以便將它們放到字符串本身上,這對函數如lower,upper和split是有意義的。 但是許多硬核Python程序員反對新的連接方法,認為它應該是列表的方法,或者它不應該移動,而只是保留舊的字符串模塊的一部分(仍然有很多其中有用的東西)。 我獨占地使用了新的連接方法,但是你會看到以任何方式編寫的代碼,如果它真的困擾你,你可以使用舊的string.join函數。

--- Mark Pilgrim,潛入Python


我同意起初它是違反直覺的,但是有一個很好的理由。 加入不能成為列表的一種方法,因為:

  • 它也必須適用於不同的迭代器(元組,生成器等)
  • 它在不同類型的字符串之間必須有不同的行為。

實際上有兩種連接方法(Python 3.0):

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

如果連接是一個列表的方法,那麼它必須檢查它的參數來決定哪一個要調用。 你不能一起加入字節和字符串,所以現在他們擁有它的方式是合理的。


這在String方法中進行了討論......最終在Python-Dev中進行了線程化,並被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)
    • 作為內置函數join
  • Guido不僅支持list s, tuple s,還支持所有序列/迭代。
  • seq.reduce(str)對於新來者來說很難。
  • seq.join(str)引入了序列對str / unicode的意外依賴。
  • join()作為內置函數只支持特定的數據類型。 所以使用內置的命名空間並不好。 如果join()支持多種數據類型,那麼創建優化的實現將很困難,如果使用__add__方法實現,那麼它是O(n²)。
  • 分隔符字符串( sep )不應省略。 顯式比隱式更好。

在這個線程中沒有其他的原因。

這裡有一些額外的想法(我自己和我的朋友):

  • Unicode支持即將到來,但它不是最終的。 那時UTF-8是最有可能取代UCS2 / 4的。 要計算UTF-8字符串的總緩衝區長度,需要知道字符編碼規則。
  • 那時,Python已經決定了一個通用的序列接口規則,用戶可以創建一個類似序列(可迭代)的類。 但Python直到2.2時才支持擴展內置類型。 那時很難提供基本的迭代類(在另一個評論中提到)。

Guido的決定被記錄在一個歷史郵件中 ,決定str.join(seq)

很有趣,但確實看起來不錯! 巴里,去吧...
--Guido van Rossum


這是因為任何迭代器都可以被連接,而不僅僅是列表,但結果和“連接器”總是字符串。

例如:

import urllib2
print '\n############\n'.join(
    urllib2.urlopen('http://data.stackexchange.com/users/7095'))




join