[python] 문자열 형식 : % vs. 형식

Python 2.6 str.format()은 기존 %연산자 와 약간 다른 구문으로 메소드를 도입했습니다 . 어느 것이 더 좋고 어떤 상황에 적합합니까?

  1. 다음은 각 방법을 사용하며 동일한 결과를 가지므로 차이점은 무엇입니까?

    #!/usr/bin/python
    sub1 = "python string!"
    sub2 = "an arg"
    
    a = "i am a %s" % sub1
    b = "i am a {0}".format(sub1)
    
    c = "with %(kwarg)s!" % {'kwarg':sub2}
    d = "with {kwarg}!".format(kwarg=sub2)
    
    print a    # "i am a python string!"
    print b    # "i am a python string!"
    print c    # "with an arg!"
    print d    # "with an arg!"
    
  2. 또한 파이썬에서 문자열 서식이 언제 발생합니까? 예를 들어, 로깅 수준이 높음으로 설정되어 있어도 다음 %작업 을 수행해도 여전히 적중 합니까? 그렇다면, 이것을 피할 수있는 방법이 있습니까?

    log.debug("some debug info: %s" % some_info)


답변

첫 번째 질문에 답하는 것은 .format여러 가지면에서 더 정교 해 보입니다. 성가신 것은 %변수 또는 튜플을 취할 수있는 방법입니다. 다음은 항상 작동한다고 생각합니다.

"hi there %s" % name

그러나이면 name발생 (1, 2, 3)합니다 TypeError. 항상 인쇄되도록하려면해야합니다.

"hi there %s" % (name,)   # supply the single argument as a single-item tuple

그건 못 생겼어 .format그런 문제가 없습니다. 또한 두 번째 예제에서는 .format예제가 훨씬 깔끔해졌습니다.

왜 사용하지 않습니까?

  • 그것에 대해 모른다 (이것을 읽기 전에 나)
  • 파이썬 2.5와 호환되어야 함

두 번째 질문에 답하기 위해 문자열 형식화 표현식을 평가할 때 문자열 형식화는 다른 작업과 동시에 발생합니다. 그리고 게으른 언어가 아닌 Python은 함수를 호출하기 전에 표현식을 평가하므로 log.debug예제에서 표현식 "some debug info: %s"%some_info은 먼저 평가됩니다. 예를 들어 "some debug info: roflcopters are active"해당 문자열이에 전달됩니다 log.debug().


답변

모듈로 연산자 (%)가 할 수없는 일, afaik :

tu = (12,45,22222,103,6)
print '{0} {2} {1} {2} {3} {2} {4} {2}'.format(*tu)

결과

12 22222 45 22222 103 22222 6 22222

매우 유용한.

format()함수 인 다른 점 은 다른 함수의 인수로 사용할 수 있습니다.

li = [12,45,78,784,2,69,1254,4785,984]
print map('the number is {}'.format,li)

print

from datetime import datetime,timedelta

once_upon_a_time = datetime(2010, 7, 1, 12, 0, 0)
delta = timedelta(days=13, hours=8,  minutes=20)

gen =(once_upon_a_time +x*delta for x in xrange(20))

print '\n'.join(map('{:%Y-%m-%d %H:%M:%S}'.format, gen))

결과 :

['the number is 12', 'the number is 45', 'the number is 78', 'the number is 784', 'the number is 2', 'the number is 69', 'the number is 1254', 'the number is 4785', 'the number is 984']

2010-07-01 12:00:00
2010-07-14 20:20:00
2010-07-28 04:40:00
2010-08-10 13:00:00
2010-08-23 21:20:00
2010-09-06 05:40:00
2010-09-19 14:00:00
2010-10-02 22:20:00
2010-10-16 06:40:00
2010-10-29 15:00:00
2010-11-11 23:20:00
2010-11-25 07:40:00
2010-12-08 16:00:00
2010-12-22 00:20:00
2011-01-04 08:40:00
2011-01-17 17:00:00
2011-01-31 01:20:00
2011-02-13 09:40:00
2011-02-26 18:00:00
2011-03-12 02:20:00


답변

Python의 logging모듈을 사용한다고 가정하면 문자열 형식화 인수를 .debug()형식화를 직접 수행하는 대신 메소드에 인수로 전달할 수 있습니다 .

log.debug("some debug info: %s", some_info)

로거가 실제로 무언가를 기록하지 않는 한 포맷팅을 피합니다.


답변

Python 3.6 (2016) 부터 f- 문자열 을 사용하여 변수를 대체 할 수 있습니다 .

>>> origin = "London"
>>> destination = "Paris"
>>> f"from {origin} to {destination}"
'from London to Paris'

f"접두사를 적어 둡니다. 파이썬 3.5 또는 이전 버전에서 이것을 시도하면을 얻을 수 있습니다 SyntaxError.

https://docs.python.org/3.6/reference/lexical_analysis.html#f-strings를 참조 하십시오.


답변

PEP 3101%파이썬 3에서 기본값 인 새로운 고급 문자열 형식으로 연산자를 대체 할 것을 제안합니다 .


답변

그러나 모든 교체 할 때 지금 내가 한 문제가 발견 한주의 해주십시오 %.format: 기존 코드의 '{}'.format(unicode_string)인코딩 UNICODE_STRING 시도하고 아마 실패 할 것이다.

이 Python 대화식 세션 로그를 살펴보십시오.

Python 2.7.2 (default, Aug 27 2012, 19:52:55)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] on linux2
; s='й'
; u=u'й'
; s
'\xd0\xb9'
; u
u'\u0439'

s문자열 (Python3에서는 ‘바이트 배열’이라고 함)이고 u유니 코드 문자열 (Python3에서는 ‘문자열’이라고 함)입니다.

; '%s' % s
'\xd0\xb9'
; '%s' % u
u'\u0439'

유니 코드 객체를 %연산자에 매개 변수로 제공 하면 원래 문자열이 유니 코드가 아닌 경우에도 유니 코드 문자열이 생성됩니다.

; '{}'.format(s)
'\xd0\xb9'
; '{}'.format(u)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u0439' in position 0: ordinal not in range(256)

그러나 .format함수는 “UnicodeEncodeError”를 발생 시킵니다 .

; u'{}'.format(s)
u'\xd0\xb9'
; u'{}'.format(u)
u'\u0439'

원래 문자열이 유니 코드 인 경우에만 유니 코드 인수로 잘 작동합니다.

; '{}'.format(u'i')
'i'

또는 인수 문자열을 문자열로 변환 할 수있는 경우 ( ‘바이트 배열’이라고 함)


답변

또 다른 장점 .format(답변에 표시되지 않음) : 객체 속성을 사용할 수 있습니다.

In [12]: class A(object):
   ....:     def __init__(self, x, y):
   ....:         self.x = x
   ....:         self.y = y
   ....:

In [13]: a = A(2,3)

In [14]: 'x is {0.x}, y is {0.y}'.format(a)
Out[14]: 'x is 2, y is 3'

또는 키워드 인수로 :

In [15]: 'x is {a.x}, y is {a.y}'.format(a=a)
Out[15]: 'x is 2, y is 3'

%내가 알 수있는 한 불가능합니다 .