본문 바로가기
Coding

Python의 문자열에 대해 알아야 할 4가지 지식 영역

by Jakegyllenhaal 2022. 5. 13.
반응형

Python의 문자열에 대해 알아야 할 4가지 지식 영역

 

Python 문자열에 대한 지식에 대한 높은 수준의 검토

Unsplash에 있는 Brett Jordan의 사진

텍스트는 정보 교환의 가장 기본적인 형태입니다. 어떤 응용 프로그램을 구축하든 관계없이 필연적으로 텍스트 정보를 어떤 방식으로든 처리해야 합니다. 따라서 Python에서 문자열을 사용하고 처리하는 데 필수적인 기술을 잘 이해하는 것이 중요합니다. 이 기사에서는 문자열에 대한 4가지 지식 영역에 대한 높은 수준의 검토를 제공하고자 합니다.

첨자를 사용하여 하나 또는 여러 문자에 액세스

문자열은 Python에서 일종의 시퀀스 데이터 유형이므로 첨자를 사용하여 개별 또는 여러 문자에 액세스할 수 있습니다. 몇 가지 예가 아래에 나와 있습니다.

greeting = "Hello, World!"assert greeting[0] == "H"
assert greeting[1:3] == "el"

하나의 인덱스만 사용하면 단일 문자를 얻게 됩니다. 슬라이싱을 사용할 때(start_index:end_index), 여러 문자가 표시됩니다. 슬라이스를 사용할 때 끝 인덱스는 포함되지 않습니다. 비연속적인 문자를 검색할 수 있도록 슬라이스에 단계를 추가할 수도 있습니다.

assert greeting[1:10:2] == 'el,Wr'

Python의 다른 시퀀스 데이터와 마찬가지로 문자열의 끝에서 문자를 검색하려는 경우 음수 인덱스를 사용할 수도 있습니다. 음수 인덱스의 경우 -1은 마지막을 의미하고 -2는 마지막이지만 하나를 의미하는 식입니다.

assert greeting[-1] == '!'
assert greeting[-3:-1] == "ld"

부분 문자열의 존재 확인

문자열은 시퀀스이기 때문에 다음의 사용을 지원한다는 의미입니다. in: substr in text 문자열에 부분 문자열이 있는지 확인합니다.

assert "Wor" in greeting

문자열의 시작 부분에 부분 문자열이 포함되어 있는지 확인하려면 다음을 사용하는 것이 좋습니다. startswith 방법. 다른 관련 방법이 있음을 알아야 합니다. endswith끝을 확인합니다.

assert greeting.startswith("Hello")
assert greeting.endswith("ld!")

부분 문자열 찾기

때로는 하위 문자열이 다른 문자열에 존재하는지 여부를 아는 것만으로는 충분하지 않습니다. 대신 정확한 위치를 알고 싶습니다. 이 경우 사용할 수 있습니다. index 또는 find.

assert greeting.index("ello") == 1
assert greeting.find("ello") == 1

둘 다 같은 일을 하는 것 같습니다. 그러나 다음을 사용하는 것이 좋습니다. find전화하기 때문에 index 문자열에 존재하지 않는 하위 문자열에서 예외가 발생하면 프로그램이 충돌할 수 있습니다.

>>> greeting.find("no_substr")
-1
>>> greeting.index("no_substr")
Traceback (most recent call last):
File "", line 1, in 
ValueError: substring not found

위의 문자열에 부분 문자열이 존재하지 않는 경우, find -1을 반환하는 동안 index 인상 ValueError.

문자열 형식 지정 및 보간에 관해서는 f-문자열에 대해 잘 알고 있어야 합니다. 보간이라고 할 때 문자열이 아닌 변수를 문자열 표현으로 변환한다는 의미입니다.

F-문자열(또는 f-문자열)은 F 또는 f를 접두사로 사용하는 문자열 리터럴이며 f는 형식화됨을 의미합니다. 다음은 간단한 f-문자열을 만드는 방법을 보여줍니다.

>>> message = f"First Message: {greeting}"
>>> print(message)
First Message: Hello, World!

문자열 연결/보간

여러 문자열/변수를 연결하려는 경우 보간을 자동으로 처리할 수 있으므로 f-문자열을 사용하는 것이 좋습니다. 다음을 사용하여 문자열을 문자열이 아닌 변수와 연결할 때 + 작업에서 모든 참가자는 문자열이어야 합니다.

price = 1.23
volume = 12
product = "water"description0 = "Product Name: " + product + "; Price: $" + str(price) + "; Volume: " + str(volume) + " oz"print(description0)
# output: Product Name: water; Price: $1.23; Volume: 12 oz

위에서 볼 수 있듯이 특히 문자열이 아닌 일부 변수를 포함하여 여러 변수에서 문자열을 구성하는 것은 매우 복잡합니다. 대조적으로 f-문자열은 이러한 연결 작업을 훨씬 간단하게 만듭니다.

description1 = f"Product Name: {product}; Price: ${price:}; Volume: {volume} oz"assert description0 == description1

우리는 f-문자열을 사용하여 description0과 일치하는 description1을 생성합니다. 알 수 있듯이 f-문자열은 서로 다른 부분 사이의 물리적 공간을 제거하여 연속 읽기를 훨씬 쉽게 만듭니다.

서식 지정자

f-문자열의 경우 다음을 사용하여 추가 형식 지정 요구 사항을 적용할 수 있는 형식 지정자에 대해서도 잘 알고 있어야 합니다. : 변수를 따릅니다. 몇 가지 예가 아래에 나와 있습니다.

# Big numbers separator
big_number = 98765432123456789
assert f"{big_number:_d}" == '98_765_432_123_456_789'# Floating numbers formatting
more_digits = 2.345678
assert f"{more_digits:.2f}" == '2.35'
assert f"{more_digits:.4f}" == '2.3457'# Scientific notation
sci_number = 0.0000043203
assert f"{sci_number:e}" == '4.320300e-06'

선형

왼쪽 또는 가운데 정렬과 같은 문자열 정렬 측면에서 형식 지정 요구 사항을 제공할 수도 있습니다. 공백을 채우기 위해 패딩을 적용할 수도 있습니다. 몇 가지 예가 아래에 나와 있습니다.

s0, s1 = 'a', 'bb'# Left-aligned with padding *
print(f'{s0:*<7}\n{s1:*<7}')
# output the following:
a******
bb*****# Right-aligned with padding %
print(f'{s0:%>8}\n{s1:%>8}')
# output the following:
%%%%%%%a
%%%%%%bb# Center-aligned
print(f'{s0:@^9}\n{s1:@^9}')
# output the following:
@@@@a@@@@
@@@bb@@@@

위에 표시된 것처럼 <를 사용하여 왼쪽 정렬을 원하고 >를 오른쪽 정렬로, ^를 사용하여 가운데 정렬을 원합니다.

사용자 정의 클래스를 정의할 때 두 가지 특수 메소드를 구현하려고 합니다. __str__ 그리고 __repr__.

__repr__ 재정의

사용자 정의 클래스에서 재정의할 수 있습니다. __repr__, 문자열을 반환해야 합니다. 보다 구체적으로, 이 문자열은 동일한 속성을 가진 다른 인스턴스 객체를 재구성하는 데 사용할 수 있습니다. 다음 예를 고려하십시오.

class Student:
def __init__(self, name: str, grade: int) -> None:
self.name = name
self.grade = grade    def __repr__(self) -> str:
print("__repr__ is invoked")
return f"Student({self.name!r}, {self.grade})"

이 클래스를 사용하여 인스턴스를 만들고 검사할 수 있습니다.

>>> student = Student("John Robinson", 6)
>>> student
__repr__ is invoked
Student('John Robinson', 6)

보시다시피 대화형 Python 콘솔에 인스턴스 변수를 입력하면 __repr__ 메서드가 호출되고 사용자 지정 인스턴스의 문자열 표현을 보여줍니다.

f-문자열에 !r 우리가 보간 할 때 self.name. 이것은 형식 변환으로 알려져 있습니다 — 우리는 이 변수가 __repr__ 방법. 여기서 문자열의 경우, !r 사용자가 재구성할 수 있도록 따옴표로 묶습니다. Student 호출하여 인스턴스 Student(‘John Robinson’, 6).

그에 비해 사용하지 않고 !r표현은 Student(John Robinson, 6), 호출되면 잘못된 구문입니다. 점에 유의하시기 바랍니다 !r 는 문자열에만 필요하며 이 예와 같이 정수에는 사용할 필요가 없습니다.

__str__ 재정의

사용자 정의 클래스에서 재정의해야 합니다. __str__, 또한 문자열을 반환합니다. __repr__에서 반환된 문자열과 비교하여 반환된 문자열은 __str__ 다음과 같이 더 많은 정보를 제공해야 합니다.

class Student:
def __init__(self, name: str, grade: int) -> None:
self.name = name
self.grade = grade    def __repr__(self) -> str:
print("__repr__ is invoked")
return f"Student({self.name!r}, {self.grade})"    def __str__(self) -> str:
print("__str__ is called")
return f"Student Name: {self.name}; Grade: {self.grade}"

업데이트된 클래스를 사용하여 다음 코드를 실행하여 __str__ 호출할 수 있습니다.

>>> student = Student("John Robinson", 6)
>>> print(student)
__str__ is called
Student Name: John Robinson; Grade: 6

인스턴스를 직접 검사하는 대신 이제 print 인스턴스와 함께 작동합니다. 보시다시피 다음으로 생성된 문자열을 얻습니다. __str__. 따라서 일반적으로 인스턴스 객체에서 print를 호출할 때 반환되는 문자열은 __str__.

Python 문자열에는 기본 텍스트 데이터 처리에 적합한 많은 방법이 있습니다. 그러나 더 복잡한 문자열 처리 작업이 있는 경우 정규식을 사용해야 할 수도 있습니다. 간단하게 하기 위해 정규 표현식을 regex라고 하겠습니다.

많은 프로그래밍 언어가 이를 통합하고 각각의 "방언"을 생성하지만 Regex는 때때로 텍스트 처리에서 별도의 언어로 간주됩니다. 특히, 대부분의 사용법은 다소 유사하며 Python을 잘 알고 있다면 다른 언어의 정규식 관련 기능을 쉽게 선택할 수 있습니다.

패턴 만들기

Python의 표준 라이브러리에서 re 모듈은 정규식에 필요한 기능을 제공합니다. 정규식을 사용하는 첫 번째 단계는 올바른 패턴을 작성하는 것입니다. 문자열로 표현되는 패턴은 문자열의 모양을 지정합니다.

일반 문자열의 경우 모양을 의미합니다. 예를 들어, “abc” 문자열이 있어야 함을 의미합니다 “abc”. 그러나 이러한 문자열은 보다 일반적인 패턴과 일치하는 여러 종류의 문자열을 감지할 만큼 강력하지 않습니다. 이를 위해 패턴 구성 요소에는 여러 범주가 있습니다.

경계 앵커
첫 번째 범주는 패턴의 접두사와 접미사에 해당합니다. 굵게 표시된 몇 가지 일반적인 앵커는 아래에 나열되어 있습니다.

^hello         starts with helloworld$         ends with world^hello world$  starts and ends with “hello world”, and thus exact matching

수량자
특정 문자열의 반복 횟수를 지정할 수도 있습니다. 그들은 수량자로 알려져 있습니다. 몇 가지 일반적인 사항은 다음과 같습니다.

he?       h followed by zero or one ehe*       h followed by zero or more ehe+       h followed by one or more ehe{3}     h followed by eeehe{1,3}   h followed by e, ee, or eeehe{2,}    h followed by 2 or more e

캐릭터 클래스
몇 개의 문자만 사용하여 많은 문자 그룹을 나타낼 수 있으므로 패턴을 크게 단순화할 수 있습니다.

\d       any decimal digit\D       any character that is not a decimal digit\s       any whitespace, including space, \t, \n, \r, \f, \v\S       any character that isn't a whitespace\w       any word character, means alphanumeric plus underscores\W       any character that is not a word character.        any character except a newline[abc]    a set of defined characters, in this case, a, b, or c

논리 연산자
Regex에는 다른 언어와 마찬가지로 자체 논리 연산자가 있습니다. 몇 가지 예가 아래에 나와 있습니다.

a|b       a or b(abc)     abc as a group[^a]      any character other than a

패턴 사용

패턴을 빌드한 후에는 의도한 대로 작동하는지 테스트할 차례입니다. 패턴이 최종적으로 작동하기 전에 패턴을 여러 번 조정해야 할 수도 있다는 점에 유의하십시오. 따라서 패턴을 수정하는 데 어려움을 겪고 있다고 걱정하지 마십시오. 패턴을 사용하는 방법에는 두 가지가 있습니다.

패턴을 여러 번 사용해야 하는 경우 프로그램에서 다시 사용할 때 시간을 절약할 수 있도록 패턴을 컴파일하는 것이 좋습니다. 이 사용법은 아래에서 찾을 수 있습니다.

import repattern = re.compile("^hi")pattern.search("hi, Python")
# output: pattern.search("hi, JavaScript")
# output: pattern.search("hello, C#")
# output: None

패턴을 한 번만 사용하면 다양한 기능을 간단하게 사용할 수 있습니다. re 모듈은 아래와 같이 표시됩니다.

re.search(r"^hi", "hi Python")
# output: 

일치 개체

문자열과 함께 패턴을 사용할 때 가장 중요한 데이터는 Match 위의 예에서와 같이 객체. 를 위해 Match 개체에는 일치 범위와 일치 항목이 포함됩니다. 일반적으로 사용되는 방법과 각각의 효과를 찾을 수 있습니다.

match = re.search(r"(\w\d)+", "xyzdda2b1c3ee")print(match)
# output: print("matched:", match.group())
# output: matched: a2b1c3print("span:", match.span())
# output: span: (5, 11)print(f"start: {match.start()} & end: {match.end()}")
# output: start: 5 & end: 11

특히, Match 개체는 True로 평가되므로 다음을 사용할 수 있습니다.

match = re.search("the_pattern", "the_string")
if match:
# when a match is found, do the operation
else:
# when a match isn't found, do the other operation

실생활 문제 해결

문제를 정리하고 실생활 문제를 해결해 봅시다. 다음 데이터가 있다고 가정합니다.

students_data = """101, John Robinson; good at maths
some random nonsense
102, Ashley Young; good at sports
54, random; record
103, Zoe Apple; All As
1234, random; record
Another random record"""

보시다시피 학생 정보가 있는 데이터에 대한 것입니다. 각 행은 학생의 정보를 나타냅니다. 그러나 텍스트 데이터에는 다른 잘못된 데이터가 포함되어 있으며 올바른 레코드를 추출하고자 합니다.

이 모든 행을 관찰하면 학생 ID 번호가 3자리 숫자이고 이름과 설명이 뒤따르는 것을 알 수 있습니다. 따라서 자세한 설명과 함께 아래의 패턴을 생각해낼 수 있습니다.

r"(\d{3}), (.+); (.+)"(\d{3}):   a group of 3 digits -> for the ID number, :        string literals, a comma and a space(.+):     a group of one or more word characters -> for the name; :        string literals, a semicolon and a space(.+):      a group of one or more characters -> for the description

이 패턴을 적용하면 원하는 레코드를 추출할 수 있습니다.

regex = re.compile(r"(\d{3}), (.+); (.+)")
desired_records = []for line in students_data.split("\n"):
match = regex.match(line)
if match:
print(f"{'Matched:':<12}{match.group()}")
desired_records.append(line)
else:
print(f"{'No Match:':<12}{line}")print(desired_records)# output the following lines:Matched:    101, John Robinson; good at maths
No Match:   some random nonsense
Matched:    102, Ashley Young; good at sports
No Match:   54, random; record
Matched:    103, Zoe Apple; All As
No Match:   1234, random; record
No Match:   Another random record

['101, John Robinson; good at maths', '102, Ashley Young; good at sports', '103, Zoe Apple; All As']

보시다시피, 정규식의 유연성을 강조하는 필요한 레코드를 올바르게 추출합니다. 일반 패턴을 만들고 여러 레코드와 일치할 수 있습니다.

이 기사에서는 Python에서 문자열을 사용하는 것과 관련된 4가지 핵심 지식 영역을 검토했습니다. 그 중 처음 세 영역은 간단해야 합니다. 정규 표현식의 경우 익숙해지기 전에 많은 연습이 필요합니다.