2013-05-22 4 views
31

내장형에있는 format 함수는 str.format 메서드의 하위 집합처럼 보이며 특히 단일 개체의 서식을 지정할 때 사용됩니다.파이썬에 형식 함수와 형식 메서드가있는 이유는 무엇입니까

예 :

>>> format(13, 'x') 
'd' 

분명히

>>> '{0:x}'.format(13) 
'd' 

선호하고 IMO가 더 좋은 모양 않지만, 왜 그냥 일을 간단하게 모든 경우에 str.format을 사용할 수 있습니까? 이 두 가지 모두 2.6에 소개되었으므로 한 번에 두 가지를 모두 갖을 충분한 이유가 있어야합니다. 무엇입니까?

편집 : 나는 약 str.formatformat 요구했다,하지 우리가 (13).format

+19

어쨌든'format()'이'.format()'보다 선호된다고 처음 들었습니다. 형식 문자열 사양에 대한 문서에서도 처음부터'.format()'을 사용합니다.이 포맷을 어디에서 얻고 있습니까? – Amber

+0

@Amber 여기에 대한 답을 보면 그렇습니다. 항상 그렇습니다. – jamylak

+0

예가 있습니까? – Amber

답변

4

나는 formatstr.format이 다른 것으로 생각합니다. 두 가지 모두에 str.format을 사용할 수 있지만 별도의 버전을 사용하는 것이 좋습니다.

최상위 레벨 format은 모든 개체가 지원하는 새로운 "서식 프로토콜"의 일부입니다. 단순히 전달 된 객체의 메소드 인 __format__을 호출하고 문자열을 반환합니다. 이것은 저수준 임무이며 Python의 스타일은 일반적으로 그 기능을 내장하는 것입니다. 파울로 스카딘 (Paulo Scardine)의 대답은 이것에 대한 이론적 근거를 설명하고 있지만 실제로는 formatstr.format의 차이점을 다루지는 않는다고 생각합니다.

str.format 메서드는 좀 더 높은 수준이며 약간 더 복잡합니다. 여러 오브젝트를 단일 결과로 형식화 할 수있을뿐만 아니라 오브젝트를 다시 정렬, 반복, 색인화 및 기타 다양한 변환을 수행 할 수도 있습니다. "{}".format(obj)을 생각하지 마십시오. str.format의 형식은 프로토콜의 같은 기계에 의존, 각 항목의 낮은 수준의 포맷에 대한

"{1} {0} {1!r}".format(obj0, obj1) # reorders, repeats, and and calls repr on obj1 
"{0.value:.{0.precision}f}".format(obj) # uses attrs of obj for value and format spec 
"{obj[name]}".format(obj=my_dict) # takes argument by keyword, and does an item lookup 

, 그래서 그것은에 자신의 노력을 집중할 수 : str.format 정말이 같은 복잡한 작업에 대한 자세한을 위해 설계되었습니다 높은 수준의 물건. 나는 실제로 그것의 인수 '__format__ 메쏘드가 아니라 내장 된 것 format을 호출하는 것을 의심한다. 그러나 그것은 구현 세부 사항이다.

("{"+format_code+"}").format(obj)format(obj, format_code)과 동일한 결과를 제공하지만, 복잡한 문자열을 확인하기 위해 형식 문자열을 구문 분석 할 필요가 없으므로 후자가 더 빠를 것으로 생각됩니다. 그러나 오버 헤드는 실제 프로그램의 노이즈에서 손실 될 수 있습니다.

스택 오버플로에 대한 예제를 포함하여 사용에 관해서는 일부 프로그래머가 format에 대해 알지 못하기 때문에 str.format이 더 많이 표시 될 수 있습니다. 이는 새롭고 상당히 모호합니다. 대조적으로 str.format을 피하기가 어렵습니다 (모든 서식 지정에 % 연산자를 사용하기로 결정하지 않은 경우). 따라서 str.format 호출을 이해하는 (사용자 프로그래머와 동료 프로그래머에게) 모든 성능 고려 사항보다 중요 할 수 있습니다.

+1

Paulo는 자신의 대답에 많은 노력을 기울였으며 모든 포괄적 인 가이드 중 하나와 같이 보입니다. 그러나 그는 존재하지 않는 질문에 대답하고 있습니다. 나는 왜 우리가 왜 항상 ''{0} '. 형식을 사용하지 않는지 알고 싶었습니다. 예'format()'이 '__format__'에 대한 구문 설탕 (syntactic sugar) 인 이유를 알고 Paulo는 왜 이것이 파이썬에 좋은지에 대해 많은 논의를했습니다. 그러나 그것은 내 질문이 아닙니다. 당신의 대답은 이유를 설명하고 논리적으로 합리적입니다. 두 가지 버전이있는 Python에 동의하지 않으면 안됩니다. "한 가지 방법"을 요구하는 것에 반대하기 때문입니다. 나는 '{0}'형식으로 간단하게 유지할 것입니다. – jamylak

37

tldr이없는 이유;formatobj.__format__을 호출하고 더 높은 수준의 항목을 수행하는 str.format 메서드에서 사용됩니다. 낮은 레벨의 경우에는 객체에 형식을 지정하는 방법을 가르치는 것이 좋습니다.

그냥 문법 설탕에게 있습니다

이 기능이 str.format에 이름과 형식 사양은 오해의 소지가 할 수있는 공유는 사실. str.format의 존재는 설명하기 쉽습니다. 복잡한 문자열 보간을 수행합니다 (이전 % 연산자 대체). format은 단일 객체를 문자열로 지정할 수 있습니다. 가장 작은 하위 집합은 str.format입니다. 그렇다면 왜 format이 필요할까요?

format 기능은 일부 OO 언어에있는 obj.format('fmt') 구조의 대안입니다. 이 결정은 len의 이유와 일치합니다 (파이썬이 x.lengthJavascript 또는 Ruby와 같은 속성 대신에 len(x) 함수를 사용하는 이유와 일치 함). 언어는 obj.format('fmt') 구조를 채택

(또는 obj.length, obj.toString 등)를, 클래스 속성이 format으로 호출 방지 할 수있다 (또는 lengthtoString을, 당신은 생각이있어) - 그렇지 않으면에서 표준 방법을 그림자 것 언어. 이 경우 언어 디자이너는 이름 충돌을 방지하기 위해 프로그래머에게 부담을주고 있습니다.

파이썬은 PoLA 매우 좋아하고 사용자 정의 속성과 언어 내장 기능 간의 충돌의 가능성을 최소화하기 위해 내장 된 기능에 대한 __dunder__ (이중 밑줄) 규칙을 채택했다. 따라서 obj.format('fmt')obj.__format__('fmt')이되고 물론 format(obj, 'fmt') 대신 obj.__format__('fmt')을 호출 할 수 있습니다 (len(obj) 대신 obj.__len__()과 같은 방식으로 호출 할 수 있음). 깨끗하고 입력하기가 쉽습니다 하나

>>> '{0:x}'.format(13) 
'd' 
>>> (13).__format__('x') 
'd' 
>>> format(13, 'x') 
'd' 

:

귀하의 예제를 사용하십니까?파이썬 디자인은 매우 실용적이지만 클리너는 아니지만 OO에 대한 파이썬의 duck-typed 접근 방식과 잘 부합되며 레거시 코드를 손상시키지 않고 기본 구현을 변경/확장 할 수있는 자유를 언어 설계자에게 제공합니다.

PEP 3101

는 새로운 str.format 방법 format을 도입 format 기능에 대한 근거에 어떤 코멘트없이 내장,하지만 구현은 분명히 단지 syntactic sugar입니다 :

def format(value, format_spec): 
    return value.__format__(format_spec) 

그리고 여기에 내가 내 경우를 휴식. 귀도 그것에 대해 말했다 무엇

인용 매우 BDFLlen (또는 공식이다는?) : 나중에 많이 와서 모든

첫째, 나는 HCI 이유 x.len() 이상 len(x)를 선택 (def __len__()). 두 개의 고리로 연결되었다는 이유는, 실제로이 둘 HCI :

(가) 일부 작업의 경우, 접두사 표기법 그냥 접미사보다 더 읽기 - 접두사 작업이 영상은 도움이 표기법을 좋아하는 수학에 오랜 전통을 가지고 (그리고 중위!) 수학자는 문제에 대해 생각합니다. 우리가 x*(a+b)과 같은 수식을 x*a + x*b으로 다시 작성하는 것의 쉬운 점을 원시 OO 표기법을 사용하여 같은 일을하는 것의 어색함과 비교하십시오.

(b) 내가 len(x)이라는 코드를 읽을 때 뭔가의 길이를 요구한다는 것을 알고 있습니다. 이것은 두 가지를 말해줍니다. 결과는 정수이고, 인수는 일종의 컨테이너입니다. 반대로, 내가 x.len()을 읽을 때, 나는 이미 x이 인터페이스를 구현하거나 표준 len()을 가진 클래스로부터 상속받은 어떤 종류의 컨테이너라는 것을 알아야합니다. 매핑을 구현하지 않는 클래스가 get() 또는 keys() 메쏘드를 가지고 있거나 파일이 아닌 무언가가 write() 메쏘드 일 때 때때로 우리가 혼란스러워하는 것을 목격하십시오.

동일한 의미로 다른 말로하면 'len'이 기본 제공 작업으로 표시됩니다. 나는 그것을 잃는 것을 싫어한다./.../

소스 : [email protected] (here도 귀도가 응답 된 원래의 질문을 가지고 원래의 게시물). Abarnert 또한 제안하십시오 Design and History FAQ에서 렌에 대한 추가 추론이있다

. 그것이 완전하거나 답이 좋지는 않지만 논쟁의 여지가없는 공식입니다. - abarnert

이 실제 우려하거나 구문 하찮은 일에 속 태우고인가?

동적 유형 지정 언어에서 변경 가능한 객체가 실제로 네임 스페이스이고 개인 메서드 또는 속성의 개념이 규칙 상 문제이므로 Python, Ruby 또는 Javascript와 같은 언어에서 매우 실용적이고 실제적인 관심사입니다.아마도 나는 그의 의견에에게보다 나은 abarnert 골로 연결되지 못했습니다 :

을 또한, 지금까지의 루비와 JS와 네임 스페이스 오염 문제로,이는 동적으로 입력 된 언어와 고유의 문제가 있음을 지적 가치가있다. Haskell 및 C++과 같이 다양한 정적 유형 언어에서 유형별 자유 함수는 가능할뿐만 아니라 관용적입니다. (The Interface Principle을 참고하십시오.) 그러나 Ruby, JS, Python과 같은 동적 유형 언어에서는 자유 함수가 보편적이어야합니다. 동적 언어에 대한 언어/라이브러리 디자인의 큰 부분은 이러한 기능을 올바르게 선택하는 것입니다.

예를 들어, 난 그냥 Angular.jsI was tired of namespace conflicts in Ember 때문에 찬성 Ember.js을 왼쪽으로 Angular는 내장 Python과 같은 밑줄 대신에 $thing을 Angular로 접두어로 붙이는 우아한 Python과 같은 전략을 사용하므로 사용자 정의 메서드 및 속성과 충돌하지 않습니다. 그렇습니다. 전체적으로 __thing__은 그리 좋지는 않지만, 매우 명확하고 객체 네임 스페이스 충돌과 관련하여 버그 클래스 인 PoLA을 피하기 때문에 Python이이 접근법을 사용하게 된 것을 기쁘게 생각합니다.

+1

나는이 두 경우가 정확히 같은 (''{0} '. format'은'x.len'과 같지 않습니다. 그것은'' '.join'와 비슷합니다.) 그러나 나는 여러분이 어디에서 왔는지를 알고 있습니다. – jamylak

+0

@jamylak : 일부 객체 언어에서는 모든 객체가'obj.format ('fmt')'와 같은 형식 메소드를 가지고 있다고 가정합니다. 파이썬에서 대신'format (obj, 'fmt')'형식이 선호되었습니다. 따라서이 함수는 이름과 형식 명세를 공유 함에도 불구하고'str.format'의 특별한 경우는 아닙니다. –

+0

''{0} '. format'도'format()'처럼 객체의'.__ format__'을 호출합니다. – jamylak

관련 문제