본문 바로가기
CS/Python

[python] string object의 count 함수 사용 시 주의사항

by Warehaus 2021. 11. 14.

Overview

 

오늘 포스팅은 코드리뷰를 진행하면서 몇 차례 피드백을 받았던 내용을 다루고자 한다.
조금 더 섬세하게, 깊이 생각했다면 이런 부분까지 놓치지 않았을 부분인데,

종종 마음이 급할 때 이런 부분을 놓치는 것 같다.

테스트 코드를 작성하는 과정에서 python unit test 에서 string의 count 내장함수를 통한 결과 확인이 필요했고,

그 확인하는 과정에서의 경험을 나누고자 한다.


아래 내용은 비단, python 에 만 한정되어 적용되는 내용이 아니며, 모든 코드에서 이런 로직은 조심해야 할 내용이다.

 

What's count?

 

count 는 단순하다. python 에서 iterable 한 자료형에서 특정 항목의 갯수를 파악해 주는 내장함수다.
다만, 오늘 얘기하고자 하는 내용은 string class의 count 이다.

사용 방법은 아래와 같다.

 

내장형 — Python 3.10.0 문서

다음 섹션에서는 인터프리터에 내장된 표준형에 관해 설명합니다. 기본 내장 유형은 숫자, 시퀀스, 매핑, 클래스, 인스턴스 및 예외입니다. 일부 컬렉션 클래스는 가변입니다. 제자리에서 멤버

docs.python.org


문자열의 범위 내에서 찾고자 하는 내용이 얼마나 들어있는 지 갯수를 카운트 해 준다.
아래는 단순한 예시이다.

 

my_string = "Hello world"
print( my_string.count("l") )


출력은 다음과 같다.

 

$ python3 str_count_01.py
3


정말 단순한 사용방법이고, 그냥 원하는 문자열을 입력하면 문자열 변수에 몇개나 있는지 카운트를 해 준다.
사실 그냥 카운트를 세고 싶은게 목적이었다면, 달리 조심해야 될 부분은 없다. 몇 개인지 파악하고 끝이기 때문이다.

count의 기능에 대해서는 어느정도 이해했으리라 본다. 정말 단어 그대로이기 때문에 어렵지 않을 것이다.
그러면 이제 count를 이용해  문자열 갯수를 파악할 때 주의해야 할 부분을 알아보자

 

Be careful to use count with string not specific.


앞서 언급은 했지만 python 코드 작성 부분에 대한 내용이었던 터라 python 카테고리로 뽑았을 뿐이지,

사실은 어느 언어에서나 조심해야 할 내용이다.

테스트가 필요한 기능과 내가 하려고 했던 확인사항은 다음과 같다.

 

- 특정 함수를 호출하면 abc0_, abc1_ , ... , abcN_ 과 같이 헤더를 만들어 주는 기능이 있다.

- 특정 헤더가 몇 개나 출력이 되었는지 아래 코드처럼 확인하고 싶었다.

 

# 여기서 header는 하드코딩하였으나, 실제로는 요청에 따른 응답 데이터이다.
headers="abc0_qweasdzcx\nabc0_123qwert\nabc1_123qwewer\nabc1_dfdf"
nh = headers.count("abc0")

s.assertEqual( nh, 2, headers )

 

결국 내가 보고싶었던 것은 headers라는 긴 문자열에서 abc0 이 몇 개나 있는지 확인하고, 내가 예상했 던 count대로 수행이 되는지 확인하고 싶었던 상황 이었다. ( 예: 특정 함수를 2번 호출 시 abc0이 2번 나와야 한다. )

 

그런데 이렇게 비교를 하게되면, abc0인 경우는 괜찮을 지 몰라도 아래와 같은 상황에서 문제가 발생한다.

 

# 여기서 header는 하드코딩하였으나, 실제로는 요청에 따른 응답 데이터이다.
headers="abc0_qweasdzcx\nabc0_123qwert\nabc1_123qwewer\nabc1_dfdf\nabc11_dfd124002f\nabc12_dddddfdf"
nh = headers.count("abc1")

s.assertEqual( nh, 2, headers )

 

이런 방식으로 비교를 하게되면,  abc1 이 abc10이 모두 카운트 되어서 원하는 테스트 수행이 아니게 된다..
( 당장은 테스트에 문제가 없더라도, 추후에 원하지 않는 결과임에도 테스트가 pass될 수 있다. )

 

그러므로 아래와 같이 정확하게 count를 비교 함으로써 더 정확한 테스트가 필요하며, 테스트 뿐만 아니라 실제 코드(headers를 만들어 내는 코드) 또한, 추후 정확한 테스트를 위해서는 정확하게 구분이 되는 header를 만들어 내야 할 필요가 생긴다.

 

아래처럼 테스트 코드를 작성한다면, 좀 더 안전하게 테스트가 가능하다.

헤더는 '_'를 가지고 있기 때문에, abc뒤의 숫자를 정확하게 포함해서 count가 가능할 것이다.

 

# 여기서 header는 하드코딩하였으나, 실제로는 요청에 따른 응답 데이터이다.
headers="abc0_qweasdzcx\nabc0_123qwert\nabc1_123qwewer\nabc1_dfdf\nabc11_dfd124002f\nabc12_dddddfdf"

# 처음 목적이었던 abc1_ 만 count하며, abc10 or abc11~1xxxx 등을 카운트 하지 않는다.
# 그리고 headers 를 생성하는 프로그램도 이런 테스트를 위해 구분자 '_' 를 반드시 두어야 할 것이다.
nh = headers.count("abc1_")

s.assertEqual( nh, 2, headers )

 

무심코 넘어갈 수 있지만 실수하기에 너무나 좋은 부분이라서 정리 해 보았다..