[python] 왜 list.join (string) 대신 string.join (list)입니까?

이것은 항상 나를 혼란스럽게했습니다. 더 좋을 것 같습니다.

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

이것보다:

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

이와 같은 특별한 이유가 있습니까?



답변

iterable (예 : list, tuple, dict, set)을 조인 할 수 있지만 결과와 “joiner” 문자열 이어야합니다 .

예를 들면 다음과 같습니다.

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

문자열 이외의 것을 사용하면 다음 오류가 발생합니다.

TypeError : sequence item 0 : 예상 str 인스턴스, int found


답변

이것은 String 메소드 에서 논의되었습니다 … 마침내 Python-Dev achive의 스레드이며 Guido에 의해 승인되었습니다. 이 스레드는 1999 년 6 월에 시작되었으며 str.join2000 년 9 월에 릴리스 된 Python 1.6에 포함되었으며 유니 코드를 지원합니다. Python 2.0 (을 str포함하여 지원되는 메소드 join)은 2000 년 10 월에 릴리스되었습니다.

  • 이 스레드에는 네 가지 옵션이 제안되었습니다.
    • str.join(seq)
    • seq.join(str)
    • seq.reduce(str)
    • join 내장 함수로
  • Guido는 lists, tuples뿐만 아니라 모든 시퀀스 / iterable 을 지원하고자했습니다 .
  • seq.reduce(str) 새로 온 사람에게는 어려움이 있습니다.
  • seq.join(str) 시퀀스에서 str / unicode에 예기치 않은 종속성이 발생합니다.
  • join()내장 함수는 특정 데이터 유형 만 지원합니다. 따라서 내장 네임 스페이스를 사용하는 것은 좋지 않습니다. join()많은 데이터 유형을 지원하는 경우 최적화 된 구현을 작성하는 것은 어려울 수 있습니다. __add__메소드를 사용하여 구현하면 O (n²)입니다.
  • 구분자 문자열 ( sep)은 생략하면 안됩니다. 암시적인 것보다 명시적인 것이 좋습니다.

이 글타래에 다른 이유가 없습니다.

여기에 몇 가지 추가 생각 (나 자신과 친구)이 있습니다.

  • 유니 코드 지원이오고 있지만 최종적인 것은 아닙니다. 당시 UTF-8은 UCS2 / 4를 대체 할 가능성이 가장 컸습니다. UTF-8 문자열의 총 버퍼 길이를 계산하려면 문자 코딩 규칙을 알아야합니다.
  • 그 당시 Python은 이미 사용자가 시퀀스와 같은 (반복 가능한) 클래스를 만들 수있는 공통 시퀀스 인터페이스 규칙을 결정했습니다. 그러나 파이썬은 내장 유형을 2.2까지 확장하는 것을 지원하지 않았습니다. 그 당시에는 기본 반복 가능 클래스를 제공하기가 어려웠습니다 (다른 의견에서 언급 함).

Guido의 결정은 다음 과 같이 결정 하는 역사적인 메일에 기록 됩니다 str.join(seq).

재밌지 만 옳은 것 같습니다! 배리, 가서 …
–Guido van Rossum


답변

join()메소드가 목록 클래스 대신 문자열 클래스에 있기 때문에 ?

나는 그것이 재미있어 보인다는 것에 동의합니다.

http://www.faqs.org/docs/diveintopython/odbchelper_join.html을 참조 하십시오 .

역사적 메모.파이썬을 처음 배웠을 때 join은 목록의 메소드가 될 것으로 예상했는데, 구분 기호를 인수로 사용합니다. 많은 사람들이 같은 방식으로 느끼고 조인 방법 뒤에 이야기가 있습니다. 파이썬 1.6 이전에는 문자열에 유용한 메소드가 없었습니다. 모든 문자열 함수를 포함하는 별도의 문자열 모듈이있었습니다. 각 함수는 문자열을 첫 번째 인수로 사용했습니다. 함수는 문자열 자체에 놓을만큼 충분히 중요하다고 여겨졌으며, 이는 하한, 상한 및 분할과 같은 기능에 적합합니다. 그러나 많은 하드 코어 파이썬 프로그래머는 새로운 조인 메소드에 반대하여 대신 목록의 메소드 여야하거나 전혀 움직이지 말고 단순히 기존 문자열 모듈의 일부를 유지해야한다고 주장했습니다. 유용한 것들).

— Mark Pilgrim, Python으로 다이빙


답변

나는 그것이 처음에는 직관적이지 않다는 데 동의하지만 그만한 이유가 있습니다. 다음과 같은 이유로 조인을 목록의 방법으로 사용할 수 없습니다.

  • 다른 iterables (튜플, 생성기 등)에서도 작동해야합니다.
  • 다른 유형의 문자열간에 다른 동작을 가져야합니다.

실제로 두 가지 조인 방법이 있습니다 (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이리스트의 메소드 인 경우, 인수 중 하나를 호출하도록 결정하기 위해 인수를 검사해야합니다. 그리고 당신은 바이트와 str을 결합 할 수 없으므로 그들이 가지고있는 방식이 합리적입니다.


답변

string.join(list)대신에 list.join(string)?

이것은 join“문자열”방법 이기 때문 입니다! iterable에서 문자열을 만듭니다. 메소드를리스트에 붙였다면리스트가 아닌 iterable이있을 때는 어떻습니까?

튜플 문자열이 있으면 어떻게 되나요? 이것이 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'

따라서 내장 문자열 메소드를 사용하는 대신 목록 메소드를 사용하려면 추가 단계를 추가해야합니다.

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

발전기를위한 성능주의 사항

파이썬이 최종 문자열을 생성하는 데 사용하는 알고리즘은 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기타 반복 가능 개체보다 개체 에 작업하는 것이 좋습니다.


답변

그것을 분리하기위한 자연스러운 직교 연산으로 생각하십시오.

반복 가능한 것에 적용 가능한 이유를 이해하고 있으므로 목록 에서만 쉽게 구현할 수 없습니다 .

가독성을 위해 언어로보고 싶지만 실제로 실현 가능하다고 생각하지 않습니다. 반복성이 인터페이스라면 인터페이스에 추가 될 수는 있지만 단지 관습이므로 중앙에 방법이 없습니다. 반복 가능한 것들에 추가하십시오.


답변

주로 a의 결과 someString.join()가 문자열 이기 때문에 .

시퀀스 (목록 또는 튜플 또는 기타)는 결과에 나타나지 않고 문자열 만 나타납니다. 결과는 문자열이므로 문자열의 메서드로 의미가 있습니다.