etc./StackOverFlow

list.join(string) 대신 string.join(list)인 이유는 무엇입니까?

청렴결백한 만능 재주꾼 2021. 12. 20. 10:11
반응형

질문자 :Evan Fosmark


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

 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: expected str instance, int found

recursive

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

  • 이 스레드에는 네 가지 옵션이 제안되었습니다.
    • str.join(seq)
    • seq.join(str)
    • seq.reduce(str)
    • join 으로 내장 된 기능
  • listtuple 뿐만 아니라 모든 시퀀스/이터러블을 지원하기를 원했습니다.
  • seq.reduce(str) 는 초보자에게 어렵습니다.
  • seq.join(str) 은 시퀀스에서 str/유니코드로의 예기치 않은 종속성을 도입합니다.
  • join() 은 특정 데이터 유형만 지원합니다. 따라서 내장 네임스페이스를 사용하는 것은 좋지 않습니다. join() 이 많은 데이터 유형을 지원하는 경우 최적화된 구현을 만드는 것이 어려울 수 있습니다. __add__ 메서드를 O(n²) 됩니다.
  • 구분자 문자열( sep )은 생략하면 안 됩니다. 명시적인 것이 암시적인 것보다 낫습니다.

다음은 몇 가지 추가 생각입니다(저와 제 친구의 생각).

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

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

웃기지만 맞는 것 같습니다! 배리, 해봐...
귀도 반 로섬


Yoshiki Shibukawa

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

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

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

역사적 메모. 내가 파이썬을 처음 배웠을 때 나는 조인이 구분 기호를 인수로 사용하는 목록의 메서드로 예상했습니다. 많은 사람들이 같은 생각을 하고 있고, 조인 방식 뒤에는 사연이 있습니다. Python 1.6 이전에는 문자열에 이러한 모든 유용한 메서드가 없었습니다. 모든 문자열 함수를 포함하는 별도의 문자열 모듈이 있었습니다. 각 함수는 문자열을 첫 번째 인수로 사용했습니다. 함수는 문자열 자체에 배치할 만큼 충분히 중요하다고 간주되었으며, 이는 lower, upper 및 split과 같은 함수에 적합했습니다. 그러나 많은 하드 코어 Python 프로그래머는 새로운 조인 방법에 반대하여 목록의 메서드가 되어야 하거나 전혀 이동하지 않고 단순히 이전 문자열 모듈의 일부로 남아 있어야 한다고 주장했습니다(여전히 많은 그 안에 유용한 것들). 나는 새로운 조인 방법을 독점적으로 사용하지만 어느 쪽이든 작성된 코드를 볼 수 있으며 정말로 귀찮다면 이전 string.join 함수를 대신 사용할 수 있습니다.

--- Mark Pilgrim, Python에 뛰어들기


Bill Karwin

처음에는 반직관적이라는 데 동의하지만 그럴만한 이유가 있습니다. Join은 다음과 같은 이유로 목록의 메서드가 될 수 없습니다.

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

실제로 두 가지 조인 방법이 있습니다(Python 3.0).

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

조인이 목록의 메서드인 경우 호출할 인수를 결정하기 위해 인수를 검사해야 합니다. 그리고 byte와 str을 함께 조인할 수 없으므로 이제 그들이 가지고 있는 방식이 의미가 있습니다.


Kiv

list.join(string) 대신 string.join(list) 이유는 무엇입니까?

join 이 "문자열" 방법이기 때문입니다! 모든 iterable에서 문자열을 생성합니다. 목록에 메서드를 붙였다면 목록이 아닌 이터러블이 있는 경우는 어떻게 됩니까?

문자열 튜플이 있으면 어떻게 될까요? 이것이 list 방법이라면 요소를 단일 문자열로 결합하기 전에 문자열의 모든 반복자를 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'

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

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

발전기에 대한 성능 주의 사항

str.join 을 사용하여 최종 문자열을 생성하는 데 사용하는 알고리즘은 실제로 iterable을 두 번 전달해야 하므로 생성자 표현식을 제공하는 경우 최종 문자열을 생성하기 전에 먼저 목록으로 구체화해야 합니다.

따라서 생성기 주위를 전달하는 것이 일반적으로 목록 이해보다 낫지만 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


Aaron Hall

분할하는 자연스러운 직교 연산으로 생각하십시오.

그것이 반복 가능한 무엇이든에 적용하고 그렇게 쉽게 단지 목록에 구현 될 수없는 이유를 나는 이해합니다.

가독성을 위해, 나는 그것을 언어로 보고 싶지만 그것이 실제로 실현 가능하다고 생각하지 않습니다. 반복 가능성이 인터페이스라면 인터페이스에 추가할 수 있지만 그것은 단지 관례일 뿐이므로 중심적인 방법이 없습니다 iterable한 세트에 추가하십시오.


Andy Dent

- "-".join(my_list) 에서 요소를 결합하여 목록으로 문자열로 변환한다고 선언합니다. 결과 지향적입니다. (쉽게 기억하고 이해하기 위해)

나는 당신의 참조를 위해 methods_of_string의 철저한 치트 시트를 만들었습니다.

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

AbstProcDo

someString.join() 의 결과가 문자열이기 때문입니다.

시퀀스(목록 또는 튜플 등)는 결과에 표시되지 않고 문자열만 표시됩니다. 결과는 문자열이기 때문에 문자열의 메서드로 이해가 됩니다.


S.Lott

둘 다 좋지 않습니다.

string.join(xs, delimit)은 문자열 모듈이 문자열과만 작동하기 때문에 비즈니스가 알지 못하는 목록의 존재를 문자열 모듈이 인식하고 있음을 의미합니다.

list.join(delimit)은 문자열이 기본 유형(언어적으로 말하면 그렇습니다)인 문자열에 너무 익숙하기 때문에 조금 더 좋습니다. a.split("\n") 의 임의의 컨텍스트에서 python 컴파일러가 a가 무엇인지 알지 못할 수 있고 (vtable 조회와 유사하게) 조회해야 하기 때문에 조인이 동적으로 전달되어야 함을 의미합니다. 여러번 하면 비싸다.

파이썬 런타임 컴파일러가 목록이 내장 모듈이라는 것을 알고 있다면 동적 조회를 건너뛰고 의도를 바이트코드로 직접 인코딩할 수 있습니다. 호출당 상속성(파이썬은 동적 언어이기 때문에 호출 사이에 조인의 의미가 변경되었을 수 있음).

슬프게도 이것이 추상화의 궁극적인 결함입니다. 어떤 추상화를 선택하든지, 추상화는 해결하려는 문제의 맥락에서만 의미가 있으며, 따라서 접착을 시작할 때 기본 이데올로기와 일치하지 않는 일관된 추상화를 가질 수 없습니다. 당신의 이념과 일치하는 관점으로 그것들을 포장하지 않고 함께하십시오. 이것을 알면 python의 접근 방식은 더 저렴하기 때문에 더 유연합니다. 자신만의 래퍼나 전처리기를 만들어 "더 멋지게" 보이게 하려면 더 많은 비용을 지불해야 합니다.


Dmitry

변수 my_list"-" 는 둘 다 객체입니다. 특히, 이들은 각각 liststr join str 클래스에 속합니다. 따라서, 구문 "-".join(my_list) 개체가 있기 때문에 사용되는 "-" 복용 my_list 입력한다.


fiftytwocards

출처 : http:www.stackoverflow.com/questions/493819/why-is-it-string-joinlist-instead-of-list-joinstring

반응형