반응형

Magic Number와 String 관리

작성 계기

 처음부터 내가 작성한 앱은 아니지만, 문자열과 상수들이 Magic Number를 관리하는 클래스에 작성이 되어 있는 것을 보고 기겁을 하였다. 무엇보다 목록이 많은 프로젝트였는데, 그 많은 목록을 일일히 타이핑을 했다는 것에 대해서 대단하게 느껴졌다. 하지만, 고객사에서는 추후라도 해외 진출도 생각을 하고 있는 것으로 보이므로 힘들지만, Magic Number와 번역 가능성이 있는 것들을 분리하기로 했다.

그리고 하는김에 분리하는 기준에 대해서 작성하다 보니 일반적인 표준이 될 것 같기 때문에 정리하여 기록을 남긴다.

Magic Number

 Magic Number는 프로그램을 개발을 하다보면 상수로 자주 사용되는 값을 말한다. 특히 string 같은 문자열의 경우 ""를 사용해서 상수형 문자열의 내용이 같으나 자주 선언을 하게 되면, 선언한 횟수 만큼 메모리를 점유하게 된다(물론 최근에는 최적화 기술이 발달해서 알아서 최적화 해줄 가능성도 크다). 또한 해당 문자열이 유지보수 과정에서 수정되어야 하는 경우에는 수정해야 하는 문자열을 찾는 과정은 상당한 일이 된다.

 따라서 대부분 초급 이상의 개발자들은 이러한 Magic Number을 특별한 네임스페이스에 따로 관리를 한다. 그리고 프로그램 실행중에는 변하지 않지만 준 Magic Number에 해당이 되는 것은 Cofigure 같은 설정값을 들 수 있다. 이러한 값들도 특별한 네임스페이스에서 관리하는 것이 개발 후반으로 갈 수 록 정신건강에 좋다.

value/string 리소스

 공식 안드로이드 개발자 가이드라인에서는 다국어 지원 서비스를 원활하게 하기 위해서는 문자열을 res/value/string.xml 에 작성하기를 권장하고 있다. 그리고 다른 언어에 대해서는 한국어에 대해서는 res/value-ko/string.xml 형식으로 관리가 된다. 물론 프로젝트 관리 메뉴에서는 string 파일이 2개로 보인다. 또한 단순히 언어만 구분을 짓는 것이 아니라 기기, 화면 비율 등에 따라서 문자열을 다르게 조절할 수 있다(자세한 것은 공식 가이드라인을 참조)

Magic Number와 value/string 리소스 구분 기준

 로직을 구현하는 문자열의 경우에는 언어에 상관이 없는 문자열들은 코드상 Magic Number로 간주하고 관리하는 것이 좋다(모드, 기능명, 분기 같은 문자열은 Magic Number로 간주).

 JAVA에서는 switch문에서 문자열로 구분을 할 수 있는 기능들이 있다. 이 switch문에서 case로 입력 받는 값은 상수형이어야 한다. 그러나 리소스에서 가져온 문자열은 일반 문자열이기 때문에 바로 swith문의 분기로 사용할 수 없다. 당연한 이야기지만, 언어가 바뀌면, 기준도 바뀌는 위험이 있기 때문이다.

덤, error: unescaped apostrophe in string 에러

종종 string.xml 에 "'"가 있는 경우에 발생하는 에러이다. 해당 문자열을 ""으로 감싸주거나, ' 앞에 \을 붙여주면 된다.

반응형

'Mobile Develop > (Android)JAVA' 카테고리의 다른 글

[Android Studio]무선 디버그(wireless debug)  (0) 2020.03.25
반응형

final 키워드

작성 계기

근래에 안드로이드 개발을 단기로 하게 되면서 전세계에서는 많이 사용하지만, 내 입장에서는 실무 개발을 해본적이 없는 JAVA로 개발을 해야 했기 때문에 기초적이지만, 기록으로 남긴다.

final의 기본 개념

final 변수

  • 한번만 초기화가 가능함.
    C/C++ 에서는 const 키워드와 성격이 거의 비슷하나 사용 방식은 차이가 있음.

    final 메서드

  • 해당 메서드를 Overide를 하거나 숨길 수 없음.
    아직 JAVA 경험이 많이 없어서 일 수 있으나, 실제로 사용된 코드를 본적은 없음

    final 클래스

  • 더 이상 상속이 불가능함.
    대표적인 사례로 java.lang.System, java.lang.String 등 있다(C++의 경우 String을 상속받아서 확장해서 사용하는 경우가 많음.)

final을 써야 하는 예시

magic number(상수)

어떤 소프트웨어를 개발을 해도 쉽게 직면하는 고민이다. 코드 유지보수와 높은 성능의 소프트웨어가 되기 위해서 magic number를 적절한 혹은 특정 namespzce 에 넣을 때 static과 함께 사용된다.

public class ConstVal {
    final static int powerCode = 0xFF;
    ...
}

익명 클래스

익명 클래스에서 변수를 참조할 때, 자신을 생성한 지역 클래스의 변수를 참조할 경우 사용. 이는 익명 클래스의 인스턴스가 살아 있으나 해당 인스턴스가 참조한 변수가 메모리상 없어지는 것을 방지하기 위해서 정해진 규칙이라 한다.

대부분은 지역 클래스라는 용어를 사용하다 보니 이해를 바로 못 하는 경우가 많은 듯 하다. 실제로 익명 클래스가 인스턴스를 만드는 시점은 지역 클래스의 메서드내에서 코드 실행중에 생성이 된다.

문제는 메서드내의 임시로 선언하고 사용한 변수들은 메서드 실행이 종료가 되면, 후에 GC에 의해서 메모리상에서 제거가 되는데, 이 때 메서드 내에서 생성된 익명 클래스의 인스턴스는 그대로 유지가 된다. 이 때 만약 이 인스턴스가 메모리에서 제거된 변수를 참조하면, 문제가 발생할 수 밖에 없다. 이 때 final 키워드를 사용하면, 해당 변수는 별도로 저장을 하기 때문에 제거가 되지는 않는다고 한다.(람다식에서도 유효한지는 차후 조사해서 추가를 해야 할 듯함.)

참조자료

반응형
반응형

Multi-Progress 표시하기

작성 계기

이미지 유사도 검색 프로토타입 엔진을 만드는 과정에서 멀티 프로그래스를 사용하게 되었다. 문제는 검색을 하는 데이터가 많기 때문에 프로토타입 종료를 위한 테스트에 사용되는 데이터의 양이 많기 때문에 로드하는 데 생각보다 시간이 많이 걸린다.

문제는 설치 및 시연 시스템을 구축업무를 다른 사람이 어느정도 진행이 되고 있는지를 표시할 화면 필요하다. 그래서 찾던 중 스택오버플러우 형님의 코드를 확인하게 되었다. 문제는 원본 url을 메모를 안해서 잊어 버렸지만;;; 뭐 검색에 시간이 걸렸으니 다른 사람에게라도 도움이 되라고 기록으로 남긴다.

주의 사항

본래 curses 모듈은 유닉스 계열 터미널에서만 지원이 된다. 하지만, windows-curses 모듈을 pip로 설치를 하면, 해결이 된다. 모듈명 등 모든 것이 본래의 curses와 같아서 해당 모듈을 사용한 python 코드는 호환이 된다. 나중에는 내장 모듈로 이관되기를 희망한다.

>pip install windows-curses

예시 코드

import curses
import time

def report_progress(filename, progress):
    """progress: 0-10"""
    stdscr.addstr(0, 0, "Moving file: {0}".format(filename))
    stdscr.addstr(1, 0, "Total progress: [{1:10}] {0}%".format(progress * 10, "#" * progress))
    stdscr.refresh()

if __name__ == "__main__":
    stdscr = curses.initscr()
    curses.noecho()
    curses.cbreak()

    try:
        for i in range(10):
            report_progress("file_{0}.txt".format(i), i+1)
            time.sleep(0.5)
    finally:
        curses.echo()
        curses.nocbreak()
        curses.endwin()

참고 자료

반응형
반응형

임의의 progress status

작성 계기

tqdm 이라는 훌륭한 progress bar 렌더링 툴이 있지만, 구닥다리 환경에서 개발할 때 필요해서 약 10분정도 생각해서 임시로 만든 progress 상태를 표시해줌. 인터페이스는 대략 tqdm과 유사하게 작성을 하였고, 기본 generator 기능을 활용하여 구현하였음.

 

작성하고 보니 역시 프로그래밍 언어 부분의 발전은 개발자의 생산성 향상에 연결된다는 생각이 들었음.

예시

import time

def prog(jobs, desc=None):
    entire = len(jobs)
    progStr = "" if desc is None else desc
    progStr += " : [{} / {}]"
    for itN, itJob in enumerate(jobs):
        print(progStr.format(itN +1, entire), end="\r")
        yield itJob
    print()

if __name__ == "__main__":
    for it in prog(range(30), desc="잉여럭"):
        time.sleep(.5)
반응형

'Python > Python3' 카테고리의 다른 글

[python3]datetime, timestamp, str 변환  (0) 2021.06.07
[python3]Multi-Progress 표시하기  (0) 2019.12.23
[python3]깊은 폴더 생성(재귀호출)  (0) 2019.08.12
[Python3]selenium 모듈 에러 노트  (0) 2019.05.21
[python3]os.path 모듈  (0) 2019.05.04
반응형

깊은 폴더 생성(재귀호출)

작성 계기

은근히 자주 작성해서 기록으로 남김

코드

def checkAndMkdir(pathStr):
    """해당 경로가 없다면 폴더를 생성한다.
    파일이 포함된 경로도 상관 없음
    """
    _, ext = os.path.splitext(pathStr)
    startPath = pathStr if not ext else os.path.dirname(pathStr)
    if not os.path.exists(startPath):
        dirUpperedPath = os.path.dirname(startPath)
        if not os.path.exists(dirUpperedPath):
            checkAndMkdir(dirUpperedPath)
        os.mkdir(startPath)
반응형

'Python > Python3' 카테고리의 다른 글

[python3]Multi-Progress 표시하기  (0) 2019.12.23
[python3]임의의 progress status  (0) 2019.12.23
[Python3]selenium 모듈 에러 노트  (0) 2019.05.21
[python3]os.path 모듈  (0) 2019.05.04
[python3, code style]not의 코드 스타일  (0) 2019.04.30
반응형

OpenCV로 끊김이 적은 동영상 재생

코드

배경이야기가 너무 길어서 두괄식으로 본론인 코드를 먼저 기록한다.

import cv2
import time
import ipywidgets as widgets
import IPython.display as display
import copy

cap = cv2.VideoCapture(video_file)
wImg = widgets.Image(
    layout = widgets.Layout(border="solid")
)
display.display( wImg)

if cap.isOpened():
    ret, img = cap.read()
    while ret:
        # 동영상 파일에서 캡쳐된 이미지를 이미지 파일 스트림으로 다시 인코딩을 한다.
        tmpStream = cv2.imencode(".jpeg", img)[1].tostring()
        wImg.value = tmpStream
        # 20 프레임이 되기 위한 딜레이 다만, 실제로 입력한 것보다 조금 더 딜레이가 있다
        time.sleep(0.05)
        ret, img = cap.read()
cap.release()

배경(도입)

이직을 하고 딥러닝 관련 프로젝트를 하게 되면서 3년만에 IPython notebook을 사용하게 되었다. 지금은 통상 jupyter로 많이 불리기는 하지만, 여전히 IPython notebook의 흔적이 남아 있다. 암튼 jupyter에서는 OpenCV에서 기본적으로 제공하는 imshow()가 정상적으로 작동이 되지 않는다. 이는 초기 OpenCV가 python에서도 동작하게 지원을 할때 독특하게 자체 자료구조인 Mat를 사용하지 않고 numpy.ndarray 자료구조를 사용하게 되면서 IPython Notebook에서 자주 사용하는 matplotlib를 사용하면서 굳이 따로 지원할 필요성을 못 느껴서 그런 것 같다. 게다가 python에 전통적으로 사용하던 IPL 라이브러리 역시 numpy.ndarray구조를 이용하여 이미지 데이터를 관리 하기 때문에 호환도 비교적 쉽다.

OpenCV의 기초인 IO(입출력) 부분에서는 기본적으로 이미지를 화면에 띄우는 것과 동영상을 재생하는 것을 기본적인 과정이다. 이 과정에서 동영상은 여러장의 이미지를 갱신하면서 재생이 된다는 것을 원리로 배울 수 있다. 문제는 matplotlib 의 pyplot 모듈을 이용해서 이미지를 화면에 보여주는데, 이 모듈은 이름에서 볼 수 있듯이 원래는 그래프와 약간이 이미지를 처리하기 위한 모듈이다. 그러다 보니 로컬에서 사용하는 OpenCV에서 처럼 동일한 윈도우에 imshow() 메서드를 호출해서 이미지만 바꿔서 동영상이 재생되는 것을 보여줄 수 없다.

필자는 구글링을 했을 때 스택오버 플로워에서는 다양한 방법들을 제시된 것을 확인 했었는데, 크게 2가지 방법이 있었다. 첫번째 방법은 IPython Notebook에 html 태그 삽입하는 방식을 사용해서 작성하는 방법, 두번째 방법은 webGL 관련 모듈을 설치하여 해당 모듈에 연결하는 방법이다. 필자는 두번째 방법을 시도했었는데, 생각보다. 프래임 드랍이 심했다.

일반적으로 사람이 실시간으로 딜레이를 못느끼는 프래임은 약 20정도인 것을 과거 다른 프로젝트를 통해서 경험을 했었다. 당연히 20프레임 이하였으니 상당한 딜레이를 느꼈던 것이다. 한동안 실망하고 잊고 있었다.

그러던 우연히 ipywidgets 이라는 IPython 자체 지원 모듈중 Image 위젯을 사용해서 이미지를 보는 보조 툴을 만들 일이 있었는데, 생각보다 이미지 파일 전환에 딜레이가 적다는 생각이 들었다. Image 위잿의 파일의 바이너리 스트림을 입력하는 부분에 동영상에서 읽은 이미지를 인코딩을 해서 연속적으로 렌더링을 하게 하면 WebGL보다 부드럽게 이미지 재생이 되지 않을까? 하는 발상으로 테스트를 해보니 생각보다 20프레임 이상 재생이 되는 것을 확인 했었다.

여기서 추가로 테스트 할 점은 코덱을 jpeg 외에 png, bmp 각각 변경해서 시도를 해봤는데, 인코딩시 스트림의 크기 클 수로 느려지는 것을 확인했다. 즉 압축률이 좋을 수록 동영상 재생의 딜레이가 적어지는 것을 알 수 있었다.

반응형
반응형

Python3 selenium 모듈 에러 노트

모듈 개요

일반적으로 웹 크롤링을 할 경우 JS를 활용하기 위해서 많이 사용된다. 관련 서적도 있기는 하다.

배경

약 300만개의 이미지가 프로젝트에서 필요해 간단하게 크롤링을 하면서 발견한 오류이다.

개발 환경

windows 10
python 3.6.8
vs code
chromedriver 74.xx

문제점

증상

살 사용하던 중 webdriver 인스턴스에서 호출되는 것은 문제가 안되는데, 메서드로 호출된 하위 element들이나 element 중에서 find_elements_by_class_name(), find_element_by_xpath(), find_elements_by_xpath() 같은 메서드를 호출하게 되면, 프로그램이 불안정하게 종료가 되어 버리는 현상이 발견되었다.

비정상적인 종료이기 때문에 chromedriver를 headless 옵션으로 실행할 경우 프로그램이 종료가 되어도 계속 프로세스가 유지 되는 현상도 있었다.

원인

execute_script()를 호출한 이후에 해당 증상이 나타난다. 전후 관계를 보았을때 selenium 모듈내의 버그로 생각된다. 에러메시지를 추적을 하면, errorNo 까지 호출은 하지만, 비정상적인 프로그램 종료가 되는 것을 보아 예외처리 부분도 아직 안된 것으로 보인다.

(임시) 해결 방법

오류를 신고를 해야 할 듯한다(귀찮다). execute_script() 실행과정에서 문제가 있고, 그 문제가 나중에 터지는 것으로 판단이 되기 때문에 일단은 webdriver 인스턴스를 refresh()를 호출하여 갱신 시킨후에 문제가 되는 메서드를 호출을 해봤다. 결과는 잘된다.문제는 중간에 이 과정으로 인해서 시간이 더 걸리게 된다.

반응형
반응형

Python3 os.path 모듈

작성하게 된 계기

C/C++ 개발자 출신 중 일부는 파일관리를 할 경우 바퀴의 재발명을 하는 경우가 많다. 물론 boost나 표준에 대해서 잘 알고 있다면 문제가 전혀 없다. 특히나 OS 크로스 플랫폼이 대세인 요즘에 OS에 따라서 (사실은 윈도우 때문에) file Path 표기법을 다르게 사용하는 문제는 어렵지는 않지만, 상당히 귀찮고 은근히 실수가 많은 분야이다. 그래서 요즘 대부분의 프로그래밍 언어들은 이러한 모듈 혹은 라이브러리를 제공을 하고 있다. 다만, 종종 이를 모르는 초보 및 현업에서 잠시 쉬신 분일 경우 모르는 경우가 있어서 기록을 남긴다. 다만, 여기는 자주 사용하는 내용만 적은 것이므로 자신이 익숙하다면 가능하면 레퍼런스를 보는 것이 좋다.

1. os.path 모듈 : 문자열 기반

내장 모듈로 경로를 다룰때 사용을 한다. 항상 파일관리 모듈을 만들경우 자주 사용하게 되는 것들을 아예 모아놓았다. 어쩌면, 경험적인 모듈이라고 볼 수 있다.

os.path.dirname

입력 받은 경로명에서 폴더(원래는 디렉토리가 표준이지만, 단어가 길어서 여기서는 편의상 폴더로 지칭함)만 출력을 해준다. 보통 파일 경로를 저장하고 있는 상태에서 폴더 경로만 알고 싶을때 많이 사용한다. 프로그램에서 파일을 관리하는 모듈을 작성할 경우 사용하기에 유용한 기능이다. 동작은 문자열 기반이다.

예시)

>>>import os
>>>os.path.dirname('/hello/world/tmp.txt')
'/hello/world'

os.path.isdir, os.path.isfile

입력 받은 경로명이 isdir의 경우 폴더이면, True이고 그외는 False를 반환하고 isfile의 경우 파일이면, True 그외는 False를 반환한다. 입력받은 문자열 기반으로 검사한다.

예시)

>>>import os
>>>os.path.isdir('C:\\hello\\world\\tmp.txt')
False
>>>os.path.isdir('C:\\hello\\world')
True
>>>os.path.isfile('C:\\hello\\world\\tmp.txt')
True
>>>os.path.isfile('C:\\hello\\world')
False

os.path.join

절대 경로와 상대경로를 조합할 경우 자주 사용하게 된다. 만약 자신이 만든 프로그램이 프로젝트 단위로 파일을 관리할 경우 프로젝트의 상위 폴더명에서 하위로 폴더를 새로 만들고 관리를 해 갈 경우에 매우 유용하다. 특이한 점은 첫 입력인자 이후 절대경로가 나오게 되면, 앞의 입력 인자로 인해 형성된 경로가 나중에 입력인자로 받은 절대경로로 초기화 되어버린다.

예시)

>>>import os
>>>os.path.join('C:\\hello\\home', 'world')
'C:\\hello\\home\\world'
>>>os.path.join('C:\\hello\\home', 'world', 'tmp.txt')
'C:\\hello\\home\\world\\tmp.txt'
>>>os.path.join('C:\\hello\\home', 'world', 'D:\\hello, 'tmp.txt')
'D:\\hello\\tmp.txt'

os.path.normcase

현재 운영체제에 맞게 경로 문자열을 정규화(Normalize)를 한다. 파이썬으로 다른 외부 모듈을 사용하다 보면 폴더의 구분자를 '/'로만 사용하는 경우가 있기 때문이다. 필자가 겪은 바로는 GUI 모듈에서 종종 그런 경우가 있다. 이 경우 해당 메서드를 사용하면 간단히 해결 된다. 대부분 윈도우 운영체제에서 사용하게 된다.

예시)

# 윈도우일 경우
>>>import os
>>>os.path.normcase('C:/hello/world')
'C:\\hello\\world'

os.path.split

내장 자료형인 str.split과 비슷하게 보이지만, 다르다. 입력받은 경로의 가장 뒷 부분에서 하나를 분리하여 2개의 string을 반환 한다. 작업중인 폴더에서 한 단계 상위 폴더 경로를 얻고 싶거나 파일경로에서 폴더 경로를 분리할 때 사용하면 유용하다.문자열 기반으로 동작을 한다.

예시)

>>>import os
# 유닉스 계열 운영체제의 경우(경로 표기가 간단해서 필자는 예시로 자주 들음)
>>>os.path.split('/hello/world/myhome')
('/hello/world', 'myhome')
>>>os.path.split('/hello/world/myhome.txt')
('/hello/world', 'myhome.txt')

# 폴더 표기를 잘못한 경우
>>>os.path.split('/hello/world/myhome/')
('/hello/world/myhome', '')

os.path.splitext

이름 그대로 확장자 부분을 분리하여 반환을 한다. 두번째 반환하는 인자가 확장자이다. 문자열 기반으로 작동을 한다. 때문에 확장자를 구분하는 .이 없을 경우에는 ''(빈)문자열를 반환한다.

예시)

>>>import os
>>>os.path.splitext('/hello/world/myhome.txt')
('/hello/world/myhome', '.txt')

# 확장자가 없는 경우
>>>os.path.splitext('/hello/world/myhome')
('/hello/world/myhome', '')

2. os.path 모듈 : 기능 기반

앞의 기능들은 대부분 문자열 기반이고 그외에 해당 경로의 파일 존재 여부나 파일 크기와 같은 것은

os.path.getctime, os.path.getmtime, os.path.getatime

윈도우에서 파일의 속성창을 열면 보이는 생성된 시각, 마지막 수정된 시각, 마지막 실행한 시각 순으로 값이 반환이 된다. 다만, os.path.getctime 의 경우 유닉스 계열 운영체제 중에서는 수정된 시각을 반환하는 경우가 있다. 반환된 시각의 단위는 초(sec) 이지만, 정수형이 아닌 실수로 표기한다.

파일 기본 속성은 파일을 열어야 알 수 있기 때문에 유닉스 계열의 경우 읽기 권한이 없는 경우 os.error를 발생 시킨다. 예외 처리를 잘 해주자.

os.path.getsize

입력인자로 받은 경로의 파일의 크기를 바이트로 반환을 해준다. 운영체제단에서 파일 크기를 알기위해서는 파일시스템에서 파일을 열어봐야 하므로 읽기 권한이 없으면, 파일을 열지 못하므로 os.error를 발생한다. 예외 처리를 잘 해주자.

참고자료

python3 공식 문서(영문)
국내 블로그 글

반응형
반응형

Python3 not의 코드 스타일

작성 계기

필자는 C/C++/C#을 주로 접한다음에 Python 을 접했기 때문에 해당 언어들은 관례상 not 연산자 !을 주로 앞에 쓰는 경우가 있다. 이유는 !는 눈에 비교적 잘 보이기 때문에 가독성을 위해서 그렇게 쓰는 버릇이 있기 때문이다. 하자만, 파이썬에서의 경우는 not 이라는 키워드를 직접 입력하기 때문에 C/C++/C#의 스타일과 다소 차이가 있다. 다만, 워낙 친인간적인 언어다 보니까 영문법과 같이 사용하는 것을 권장한다.

not의 코딩 스타일

다음은 코딩 스타일 비교이다. 결과적으로는 둘다 같은 결과를 얻을 수 있다.

전통적인 스타일

예시)

>>>tmpNum = 1
>>>not type(tmpNum) is str
True
>>>not type(tmpNum) is int
False

구글 코딩 스타일

예시)

>>>tmpNum = 1
>>>type(tmpNum) is not str
True
>>>type(tmpNum) is not int
False

어떤 방식이 좋은가?

두 예시에서 보듯이 결과적으로는 같기 때문에 사실은 상관이 없다. 하지만, 구글 코딩 스타일을 더 권장을 하는데, 이유는 앞에 괄호 없이 not이 있다보면, 가독상 사람입장에서는 (not type(tmpNum)) is str 으로 읽은 가능성이 있고, 경우에 따라서 잘못 의미를 해석할 수 있기 때문이다. 그밖에 성능상에서도 큰 차이는 없다.

반응형
반응형

Python3 : 삼항연산자(Ternary Operators)

작성한 계기

C를 먼저 익힌 개발자라면 3상연산자는 라인수는 적으면서 간단하게 조건문을 사용할 경우에 많이 사용한다. 다만, 파이썬에서는 전통적인 삼항연사자와 다르게 표현이 되어서 당황했었다. 그래서 기록으로 남긴다.

전통적인 삼항연산자

전통적으로 C/C++/C#과 같은 언어에서는 ? 기호를 삼항식으로 사용해왔다.

예시)

#include <stdio.h>

void TwoMultiple(const int num)
{
    printf("%d is %s\n", num, (num % 2 ? "even" : "odd"));
}

int main(const int argc, const char* argv[])
{
    TwoMultiple(1);
    // 1 is odd
    TwoMultiple(2);
    // 2 is even
    return 0;
}

화면 출력 코드가 길어서 코드가 길어지지만, 삼항식자체는 짧다.

파이썬의 삼항연산자

파이썬에서 삼항연산자는 처음부터 있던 것은 아니고 요구에 의해서 생기게 되었는데, 기존의 전통적인 방식과 많이 다르기에 많은 고심이 있던 것으로 생각된다. 간결한 기호를 사용하지 않고 기존의 if/else문을 한줄로 표현하는 방식을 사용하고 있다. if키워드 앞에 오는 값은 참(True)일때, else 다음에 오는 것은 거짓(False)일때 수행을 하게 된다. 그리고 if와 else 사이에는 조건문이 삽입되어 있는 구조이다.
예시)

def twoMultiple(num):
    resultStr = str(num) + ' is ' + ('odd' if num % 2 else 'even')
    print(resultStr)

twoMultiple(1)
# 1 is odd
twoMultiple(2)
# 2 is even

이전의 전통적인 삼항연산자보다는 좀 더 친 인간적인(?) 문법이 되었다. 그러나 대신 전통적인 삼항연산자 보다는 길어진 느낌이 있다. 또, 파이썬의 들여쓰기를 통한 scope를 구분한다는 효과와 함께 삼항연산자는 C/C++ 만큼 자주 사용하지 않을 것으로 보인다. 그리고 이 삼항연산자 패턴은 for문을 이용한 자료형 변경하는 패턴에서도 볼 수 있다.

삼항연산자를 보면서 느낀점

대부분의 프로그래밍 언어도 그렇지만, 활발하게 필요한 기능이 있다면 추가가 되고 있다. 다만 파이썬에서 전통적인 문법과 다른 것을 볼 때 마다 느끼는 것이 기능을 바로 추가 하지 않고 좀 더 나은 방법이 있는지 고민하면서 추가를 한다는 느낌을 받았다.

참조 자료

python 계단 밟기

반응형

+ Recent posts