공유 블로그

뭐라고 설명하기 어렵네여;;(제목 짓기 어려웠습니다.ㅎ;;)

일단 아래 결과물로 보시면 바로 이해 가실 겁니다.

 

결과물

위와 같이 내용의 개수를 세서 자동적으로 구분선을 만들어 깔끔하게 출력하는 함수를 만들어 봤습니다.

한글, 영어 특수문자 등 자릿수 확인합니다.

코드 보시면 쉽게 이해 가실 겁니다.

소스코드

2022/09/17 코드

더보기
import math


# 문자열 개수 세기(영어 제외한 한글, 다른 나라언어 : +2 나머지 : +1)
def stringCountLine(string: str):
    count = 0
    for character in string:
        # print(count, character, character.isalpha())
        # 영어 판단
        if 'a' <= character <= "z" or 'A' <= character <= 'Z':
            count += 1
        # 나머지 문자(한글, 다른 나라언어 등)
        elif character.isalpha():
            count += 2
        # 진짜 나머지 문자(숫자, 특수문자 등)
        else:
            count += 1
    # print(count)
    return count


# 제목 구분선 길이 계산
def makeDividingLine(titleName: str, totalContentLength: int):
    # 내용 개수 세기
    titleLength = stringCountLine(titleName)

    # print(titleLength, '|', totalContentLength, '->', totalContentLength/2)

    # 내용보다 제목이 길 경우
    if titleLength > totalContentLength:
        calc = titleLength - totalContentLength
        # print('({} - {}) / 2 ='.format(titleLength,
        #       totalContentLength, totalLen), end=' ')

    else:
        calc = totalContentLength - titleLength
        # print('({} - {}) / 2 ='.format(totalContentLength,
        #       titleLength, totalLen), end=' ')

    # 구분선 길이 계산
    totalLen = calc/2
    # 정수, 실수 구분을 위함
    REST = calc % 2

    # print('길이 :', totalLen)
    # print('올림길이 :', math.ceil(totalLen))

    # print('실수, 정수 판단 :', REST)

    # 최종 출력내용
    returnData = '{0}{1}{0}'.format('-'*math.ceil(totalLen), titleName)

    # 실수일 경우
    if REST:
        return returnData, totalLen, titleLength
    # 정수일 경우
    else:
        return returnData, int(totalLen), titleLength


# 최종 결과물 출력
def dividingAfter(titleName: str, realContent: str):
    # 내용 개수 세기
    realContentCount = stringCountLine(realContent)

    # 제목 구분선 출력
    dividingLine = makeDividingLine(titleName, realContentCount)

    # print(type(dividingLine[1]), '== float -> ',
    #       type(dividingLine[1]) is float)

    print(dividingLine[0])
    print(dividingLine[2], realContentCount)
    if dividingLine[2] > realContentCount:
        print('WARNING : 제목이 내용보다 깁니다!!')
        # 이부분 주석을 해제 하시면 정상적으로 출력하는 것을 볼수 있습니다.(NEW 추가됨)
        # return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*stringCountLine(dividingLine[0]))

    # 제목 구분선이 실수일 경우
    if type(dividingLine[1]) is float:
        return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*(realContentCount+1))

    # 나머지
    return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*realContentCount)


# 사용법
print(dividingAfter(' 제목 ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' 제목 ', 'hello? nice meet you.'))
print(dividingAfter(' 제목 ', '안녕하세요? nice meet you.'))

print(dividingAfter(' content ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' content ', 'hello? nice meet you.'))
print(dividingAfter(' content ', '안녕하세요? nice meet you.'))

print(dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' 이것은 제목 입니다. ', 'hello? nice meet you.'))
print(dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? nice meet you.'))

print(dividingAfter(' this is 제목 ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' this is 제목 ', 'hello? nice meet you.'))
print(dividingAfter(' this is 제목 ', '안녕하세요? nice meet you.'))


print(dividingAfter('안녕하세요? nice meet you.', ' this is 제목 '))

2022/09/25 수정내용

더보기

1. 내용에 '\n' 모두 포함해서 구분선이 길어지는 버그가 있었습니다.(해결함)

2. 또한 '\t'이(가) 있을경우 4칸씩 증가해야 되는걸 노쳤습니다.(해결함)

import math


# 문자열 개수 세기(한글, 다른 나라언어 : +2 나머지 : +1)
def stringCountLine(string: str):
    count = 0

    if '\n' in string:
        string = max(string.split('\n'), key=len)

    for character in string:
        # print(count, character, character.isalpha())
        # 영어 판단
        if 'a' <= character <= "z" or 'A' <= character <= 'Z':
            count += 1
        elif '\t' in character:
            count += 4
        # 나머지 문자(한글, 다른 나라언어 등)
        elif character.isalpha():
            count += 2
        # 진짜 나머지 문자(숫자, 특수문자 등)
        else:
            count += 1
    # print(count)

    return count


# 제목 구분선 길이 계산
def makeDividingLine(titleName: str, totalContentLength: int):
    # 내용 개수 세기
    titleLength = stringCountLine(titleName)

    # print(titleLength, '|', totalContentLength, '->', totalContentLength/2)

    # 내용보다 제목이 길 경우
    if titleLength > totalContentLength:
        calc = titleLength - totalContentLength
        # print('({} - {}) / 2 ='.format(titleLength,
        #       totalContentLength, totalLen), end=' ')

    else:
        calc = totalContentLength - titleLength
        # print('({} - {}) / 2 ='.format(totalContentLength,
        #       titleLength, totalLen), end=' ')

    # 구분선 길이 계산
    totalLen = calc/2
    # 정수, 실수 구분을 위함
    REST = calc % 2

    # print('길이 :', totalLen)
    # print('올림길이 :', math.ceil(totalLen))

    # print('실수, 정수 판단 :', REST)

    # 최종 출력내용
    returnData = '{0}{1}{0}'.format('-'*math.ceil(totalLen), titleName)

    # 실수일 경우
    if REST:
        return returnData, totalLen, titleLength
    # 정수일 경우
    else:
        return returnData, int(totalLen), titleLength


# 최종 결과물 출력
def dividingAfter(titleName: str, realContent: str):
    # 내용 개수 세기
    realContentCount = stringCountLine(realContent)

    # 제목 구분선 출력
    dividingLine = makeDividingLine(titleName, realContentCount)

    # print(type(dividingLine[1]), '== float -> ',
    #       type(dividingLine[1]) is float)

    # print(dividingLine[0])
    # print(dividingLine[2], realContentCount)
    if dividingLine[2] > realContentCount:
        print('WARNING : 제목이 내용보다 깁니다!!')
        # 이부분 주석을 해제 하시면 정상적으로 출력하는 것을 볼수 있습니다.(NEW 추가됨)
        return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*stringCountLine(dividingLine[0]))

    # 제목 구분선이 실수일 경우
    if type(dividingLine[1]) is float:
        return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*(realContentCount+1))

    # 나머지
    return '{}\n{}\n{}\n'.format(dividingLine[0], realContent, '-'*realContentCount)


# 사용법
print(dividingAfter(' 제목 ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' 제목 ', 'hello? nice meet you.'))
print(dividingAfter(' 제목 ', '안녕하세요? nice meet you.'))

print(dividingAfter(' content ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' content ', 'hello? nice meet you.'))
print(dividingAfter(' content ', '안녕하세요? nice meet you.'))

print(dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' 이것은 제목 입니다. ', 'hello? nice meet you.'))
print(dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? nice meet you.'))

print(dividingAfter(' this is 제목 ', '안녕하세요? 반갑습니다.'))
print(dividingAfter(' this is 제목 ', 'hello? nice meet you.'))
print(dividingAfter(' this is 제목 ', '안녕하세요? nice meet you.'))


print(dividingAfter('안녕하세요? nice meet you.', ' this is 제목 '))

2023/01/08 수정내용

더보기

1. 코드 강화

from __future__ import annotations

import math
import warnings
import inspect

import pandas as pd


# 구분선 관련 클래스
class about_dividing_Function:
    # 문자열 개수 세기(한글, 다른 나라언어 : +2 | 영어, 나머지 : +1 | 탭 +1)
    def stringCountLine(self, string: str, details=False, DEBUG=False):
        if details:
            record = {}

        def _stringCount(string: str):
            count = 0
            for character in string:
                # print(count, character, character.isalpha())
                # 영어 판단
                if 'a' <= character <= "z" or 'A' <= character <= 'Z':
                    count += 1
                elif '\t' in character:
                    count += 4
                # 나머지 문자(한글, 다른 나라언어 등)
                elif character.isalpha():
                    count += 2
                # 진짜 나머지 문자(숫자, 특수문자 등)
                else:
                    count += 1

            if details:
                record[string] = count

            if DEBUG:
                print(f'{string} -> {count}')

            return count

        if '\n' in string:
            string = max(string.split('\n'), key=_stringCount)

        if details:
            return _stringCount(string), record

        return _stringCount(string)

    # 제목 구분선 출력
    def printDivideTitle(self, titleName: str, dividingLine: str = '-', lineCount: int = 0):
        if type(lineCount) is not int:
            warnings.warn('lineCount길이는 정수 여야 합니다.')
            return False
        #             제목 전체 길이, 구분선 전체 길이
        totalLength = len(titleName)+(lineCount*2)
        return titleName.center(totalLength, dividingLine)

    # 제목 구분선 길이 계산
    def makeDividingLine(self, titleName: str, totalContentLength: int, dividingLine: str = '-'):
        if type(totalContentLength) is str:
            totalContentLength = self.stringCountLine(totalContentLength)

        # 내용 개수 세기
        titleLength = self.stringCountLine(titleName)

        # 내용보다 제목이 길 경우
        if titleLength > totalContentLength:
            calc = titleLength - totalContentLength
        else:
            calc = totalContentLength - titleLength

        # 구분선 길이 계산
        drew_Divding_totalLen = math.ceil(calc/2)

        # 최종 출력내용
        returnData = self.printDivideTitle(
            titleName, dividingLine, drew_Divding_totalLen
        )

        # 제목에 구분선 출력, 구분선만의 개수(반쪽), 구분선 제외 제목 길이(한글 포함시 +2 -> stringCountLine함수 참조)
        return returnData, drew_Divding_totalLen, titleLength

    # 제목 기준 마지막 구분선 출력
    def endDividingLine(self, title, dividingLine: str = '-'):
        return dividingLine*self.stringCountLine(title)

    # 최종 결과물 출력
    def dividingAfter(self, titleName: str, realContent: str, drawDividing: str = '-', showWarning: bool = True, showDetailsValue=False):
        # 내용 개수 세기
        realContentCount, details = self.stringCountLine(
            realContent, details=True)

        # 제목 구분선 출력
        dividingLine = self.makeDividingLine(
            titleName, realContentCount, drawDividing
        )

        def returnData(showValue=False) -> (str | dict):
            for k, v in details.items():
                if v:
                    total = realContent.replace(k, f'{dividingLine[0]}\n{k}')
                    break

            text = f'{total}\n{self.endDividingLine(dividingLine[0], drawDividing)}\n'
            if showValue:
                details_Value = {
                    'text': text,
                    'Only_Dividing_Count(half)': dividingLine[1],
                    'Console_Title_Length': dividingLine[2],
                    'Draw_Dividing': drawDividing
                }
                return details_Value
            else:
                return text

        # 구분선 제외 제목 길이가 내용보다 클경우
        if dividingLine[2] > realContentCount:
            if showWarning:
                warnings.warn('WARNING : 제목이 내용보다 깁니다!!')
                return False
            else:
                # 이부분 주석을 해제 하시면 정상적으로 출력하는 것을 볼수 있습니다.
                return returnData(showDetailsValue)

        return returnData(showDetailsValue)

    # 변수의 내용에 구분선 출력(시작 -> 변수 이름 생성, 끝 -> 구분선 생성)
    def dividing(self, VariableContent, drawDividing='-') -> (str | Exception):
        callers_local_vars = inspect.currentframe().f_back.f_locals.items()
        df = pd.DataFrame(callers_local_vars)
        df.columns = ['함수명', '값']

        try:
            variableName = df[(df['값'] == VariableContent)].iloc[0]['함수명']
        except Exception as e:
            warnings.warn(str(e))
            return e

        return self.dividingAfter(
            f' {variableName} ',
            VariableContent,
            drawDividing=drawDividing
        )


if __name__ == '__main__':
    ADF = about_dividing_Function()
    # 사용법
    print(ADF.dividingAfter(' 제목 ', '안녕하세요? 반갑습니다.'))
    print(ADF.dividingAfter(' 제목 ', 'hello? nice meet you.'))
    print(ADF.dividingAfter(' 제목 ', '안녕하세요? nice meet you.'))

    print(ADF.dividingAfter(' content ', '안녕하세요? 반갑습니다.'))
    print(ADF.dividingAfter(' content ', 'hello? nice meet you.'))
    print(ADF.dividingAfter(' content ', '안녕하세요? nice meet you.'))

    print(ADF.dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? 반갑습니다.'))
    print(ADF.dividingAfter(' 이것은 제목 입니다. ', 'hello? nice meet you.'))
    print(ADF.dividingAfter(' 이것은 제목 입니다. ', '안녕하세요? nice meet you.'))

    print(ADF.dividingAfter(' this is 제목 ', '안녕하세요? 반갑습니다.'))
    print(ADF.dividingAfter(' this is 제목 ', 'hello? nice meet you.'))
    print(ADF.dividingAfter(' this is 제목 ', '안녕하세요? nice meet you.'))

    print(
        ADF.dividingAfter(
            ' 안녕하세요? nice meet you. ',
            ' this is 제목 ',
            showWarning=False
        )
    )

공유하기

facebook twitter kakaoTalk naver band kakaostory Copy URL