これはいつも私を混乱させています。これはより良いように思えます:
my_list = ["Hello", "world"]
print my_list.join("-")
# Produce: "Hello-world"
これより:
my_list = ["Hello", "world"]
print "-".join(my_list)
# Produce: "Hello-world"
このような特別な理由はありますか?
これは、リストだけでなく、あらゆるイテラブルを結合できるからです。しかし、結果と "joiner"は常に文字列です。
例えば:
import urllib2
print '\n############\n'.join(
urllib2.urlopen('http://data.stackexchange.com/users/7095'))
これはPython-Devの Stringメソッド...やっと threadで議論され、Guidoに受け入れられました。このスレッドは1999年6月に始まり、str.join
は2000年9月にリリースされた(そしてUnicodeをサポートした)Python 1.6に含まれました。 Python 2.0(str
を含むjoin
メソッドをサポート)は2000年10月にリリースされました。
str.join(seq)
seq.join(str)
seq.reduce(str)
join
list
s、Tuple
sだけでなく、すべてのシーケンス/イテラブルをサポートしたいと考えていました。seq.reduce(str)
は初心者にとって難しいです。seq.join(str)
はシーケンスからstr/unicodeへの予期しない依存性をもたらします。join()
は特定のデータ型のみをサポートします。そのため、組み込みの名前空間を使用するのは良くありません。 join()
が多くのデータ型をサポートしている場合、最適化された実装を作成するのは難しいでしょう。もし__add__
メソッドを使って実装されているならO(n²)です。sep
)は省略しないでください。明示的は暗黙的より優れています。このスレッドに他の理由はありません。
ここにいくつかの追加の考えがあります(私自身、そして私の友人のもの)。
Guidoの決定は 履歴メール に記録され、str.join(seq)
を決定します。
おかしいです、しかしそれは正しいようです!バリー、それに行きなさい...
- グイド・ヴァン・ロッサム
join()
メソッドはリストクラスではなく文字列クラスに入っているのですか?
面白そうだね.
http://www.faqs.org/docs/diveintopython/odbchelper_join.htmlを参照してください :
過去のメモ 初めてPythonを学んだとき、joinはリストのメソッドであることを期待していました。リストのメソッドは引数としてデリミタを取ります。多くの人が同じように感じており、joinメソッドの背後にはストーリーがあります。 Python 1.6より前では、文字列はこれらの便利なメソッドをすべて持っていませんでした。すべての文字列関数を含む別の文字列モジュールがありました。各関数は最初の引数として文字列を取りました。これらの関数は、文字列自体に配置するのに十分なほど重要であると見なされていました。これは、lower、upper、splitなどの関数にとって意味がありました。しかし、多くの中核的なPythonプログラマーは新しいjoinメソッドに反対し、それは代わりにリストのメソッドであるべきか、あるいはまったく動くべきではなく単に古いstringモジュールの一部のままにすべきだと主張しましたその中に便利なものの)。私は排他的に新しいjoinメソッドを使っていますが、どちらの方法で書かれたコードも見ることができますし、それが本当に気になる場合は、代わりに古いstring.join関数を使うことができます。
--- Mark Pilgrim、Pythonに飛び込む
最初は直感に反すると思いますが、それには正当な理由があります。 Joinはリストのメソッドにはなれません。
実際には2つのjoinメソッドがあります(Python 3.0):
>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>
Joinがリストのメソッドであれば、その引数を調べてどれを呼び出すかを決める必要があります。そして、あなたはbyteとstrを一緒に結合することはできません。
なぜ
string.join(list)
ではなくlist.join(string)
なのですか?
これはjoin
が "文字列"メソッドだからです!それは任意のiterableから文字列を作成します。リストにメソッドを貼り付けた場合、リストではないイテラブルがあるとどうなりますか?
あなたが文字列のタプルを持っているとどうなりますか?これがlist
メソッドの場合、要素を単一の文字列に結合する前に、そのような文字列のすべてのイテレータをlist
としてキャストする必要があります。例えば:
some_strings = ('foo', 'bar', 'baz')
私たち自身のリストのjoinメソッドを転がしましょう:
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
で最終文字列を作成するために使用するアルゴリズムは、実際にはイテラブルを2回渡す必要があるため、ジェネレータ式を指定する場合は、最終文字列を作成する前にリストに具体化する必要があります。
したがって、ジェネレータを迂回する方が通常リスト内包表記よりも優れていますが、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
オブジェクトの上にそれを持つことはまだ理にかなっています。
それを分割するための自然な直交操作と考えてください。
私はなぜそれがイテレータブルなものにも適用可能で、簡単に実装できないのか ちょうど リスト上で - 理解しています。
読みやすさのために、私は言語でそれを見たいのですが、私はそれが実際に実行可能であるとは思わない - もし反復可能性がインターフェースであればそれはインターフェースに追加されることができる反復可能なものの集合にそれを追加します。
someString.join()
の結果は文字列だからです。
シーケンス(リスト、タプル、その他)は結果には現れず、単なる文字列です。結果は文字列なので、文字列のメソッドとして意味があります。
" - "の-
。join(my_list)は、リストの要素を結合することで文字列に変換することを宣言します。結果を重視しています。
参考のため、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']}
どちらもいいじゃない。
string.join(xs、delimit)は、文字列モジュールは文字列に対してのみ機能するため、文字列モジュールがリストの存在を認識していることを意味します。
list.join(delimit)は、文字列が基本的な型であることに慣れているので(そして言語的にはそうであるため)、もう少し優れています。しかし、これはjoinが動的にディスパッチされる必要があることを意味します。なぜなら、a.split("\n")
の任意のコンテキストではpythonコンパイラはaが何であるかを知らず、それを調べる必要があるからです。何度も。
リストが組み込みモジュールであることをPythonランタイムコンパイラが知っていれば、動的ルックアップをスキップしてその意図を直接バイトコードにエンコードすることができます。それ以外の場合、動的に "a"の "join"を解決する必要があります。呼び出しごとの継承権(pythonは動的言語であるため、呼び出し間で結合の意味が変わる可能性があります)。
残念ながら、これは抽象化の究極の欠陥です。どの抽象化を選択しても、その抽象化は解決しようとしている問題の文脈でしか意味がありません。したがって、それらを接着し始めても根本的なイデオロギーと矛盾しない一貫した抽象化はできません。あなたのイデオロギーと一致する見方でそれらを包むことなく一緒に。これを知って、pythonのアプローチはより安いのでより柔軟です、あなた自身のラッパーまたはあなた自身のプリプロセッサを作ることによって、それを "よりきれいに"見せるためにもっと支払うのはあなた次第です。