콘텐츠로 건너뛰기

파이썬에서 상수 사용하기

[

Python 상수: 코드의 유지 보수성 향상

프로그래밍에서 상수는 프로그램의 실행 중에 변경되지 않는 값을 나타내는 이름을 의미합니다. 상수는 프로그래밍에서 기본 개념이며, Python 개발자들은 많은 경우에 이를 사용합니다. 그러나 Python에는 상수를 정의하기 위한 특별한 구문이 없습니다. 실제로, Python의 상수는 변경되지 않는 변수입니다.

상수로 지정된 이름에 재할당을 방지하기 위해, Python 커뮤니티가 채택한 네이밍 컨벤션은 _대문자_를 사용하는 것입니다. 모든 Python 프로그래머는 상수가 무엇이고, 왜 그리고 언제 사용해야 하는지를 알고 있어야 합니다.

이 튜토리얼에서는 다음을 알게 됩니다:

  • Python에서 상수를 적절하게 정의하는 방법
  • 몇 가지 내장 상수 식별하기
  • 상수를 사용하여 코드의 가독성, 재사용성, 유지 보수성 향상시키기
  • 프로젝트에서 상수를 구성하고 관리하는 다양한 접근 방식 적용하기
  • Python에서 상수를 엄격하게 상수로 만드는 여러 기법 사용하기

상수를 정의하고 사용하는 방법을 익힘으로써 코드의 가독성, 유지 보수성 및 재사용성을 크게 개선할 수 있습니다.

이 튜토리얼에서 최대한 많은 예제 코드를 포함하여 상세하고 단계적인 실행 가능한 샘플 코드를 제공합니다.

상수와 변수의 이해

변수상수는 컴퓨터 프로그래밍에서 역사적으로 매우 중요한 개념입니다. 대부분의 프로그래밍 언어는 데이터를 조작하고 효과적이고 논리적인 방식으로 작업하기 위해 이러한 개념을 사용합니다.

변수와 상수는 여러분이 쓰게 될 모든 프로젝트, 앱, 라이브러리 또는 기타 코드 조각에 존재할 확률이 높습니다.

변수와 상수 중에서도 변수는 변경 가능한 값이고 상수는 변경되지 않는 값입니다. 그러므로, 상수는 프로그램 실행 동안 항상 동일한 값을 유지합니다.

변수란 무엇인가요?

변수는 값을 저장하는 메모리 공간을 가리키는 이름(식별자)입니다. 변수에 값을 할당하면 그 값을 언제든지 변경할 수 있습니다. 변수는 값을 저장하고 참조하는 데 사용됩니다.

다음은 Python에서 변수를 사용하는 간단한 예입니다:

x = 5
y = 10
z = x + y
print(z) # 출력: 15

상수란 무엇인가요?

상수는 프로그램의 실행 중에 변경되지 않는 값을 나타내는 변수입니다. 상수는 프로그램에서 변하지 않는 데이터를 표현하는 데 사용됩니다. 예를 들어, 수학적인 상수인 pi (π)는 원주율을 나타냅니다.

Python에는 상수를 정의하기 위한 특별한 구문이 없지만, 상수를 대문자로 작성하여 변수로 사용될 때 재할당을 방지하기 위한 네이밍 컨벤션이 존재합니다. 이러한 네이밍 컨벤션을 따르면 프로그래머가 상수로 지정한 변수의 값이 의도적으로 변경되지 않았음을 알 수 있습니다.

예를 들어, 다음은 Python에서 상수로 작명된 변수의 예입니다:

PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348

이렇게 상수로 작명된 변수는 프로그램에서 읽을 수 있는 값을 유지합니다. 변수명이 대문자로 작성되었으므로 이 변수는 상수로 취급되고, 다른 값으로 재할당되지 않아야 합니다.

상수는 프로그램의 여러 부분에서 공유되어야 하는 값이며, 변하지 않는 값을 사용해야 하는 경우에 유용합니다. 상수를 사용하면 값을 여러 곳에서 일관되게 사용할 수 있으므로 코드의 가독성과 유지 보수성이 향상됩니다.

상수를 사용해야 하는 이유는 무엇인가요?

상수를 사용하는 이유는 다음과 같습니다:

1. 가독성 향상: 상수를 사용하면 프로그램의 여러 곳에서 동일한 값을 사용할 수 있습니다. 이렇게 하면 코드가 더 읽기 쉬워지고, 값을 직접 사용하는 것보다 가독성이 향상됩니다.

# 변수를 사용한 예
radius = 5
circumference = 2 * 3.14159 * radius
print(circumference)
# 상수를 사용한 예
PI = 3.14159
radius = 5
circumference = 2 * PI * radius
print(circumference)

2. 재사용성 향상: 상수를 사용하면 동일한 값을 반복해서 작성할 필요가 없습니다. 한 번 정의된 상수는 프로그램의 여러 부분에서 재사용될 수 있으며 코드의 재사용성을 높일 수 있습니다.

# 변수를 사용한 예
radius = 5
area = 3.14159 * radius * radius
circumference = 2 * 3.14159 * radius
print(f"The area of the circle is {area}")
print(f"The circumference of the circle is {circumference}")
# 상수를 사용한 예
PI = 3.14159
radius = 5
area = PI * radius * radius
circumference = 2 * PI * radius
print(f"The area of the circle is {area}")
print(f"The circumference of the circle is {circumference}")

3. 유지 보수성 향상: 상수를 사용하면 프로그램에서 논리적인 상수를 사용하므로 코드 변경에 따른 유지 보수가 더 쉬워집니다. 상수를 사용하면 값을 한 곳에서만 변경하면 되므로 코드를 업데이트하는 데 드는 작업과 리스크가 줄어듭니다.

# 변수를 사용한 예
tax_rate = 0.0625
subtotal = 100
tax = subtotal * tax_rate
total = subtotal + tax
print(f"The tax is {tax}")
print(f"The total is {total}")
# 상수를 사용한 예
TAX_RATE = 0.0625
subtotal = 100
tax = subtotal * TAX_RATE
total = subtotal + tax
print(f"The tax is {tax}")
print(f"The total is {total}")

상수를 사용하여 코드의 가독성, 재사용성 및 유지 보수성을 향상시킬 수 있습니다. 개발자로서 Python의 상수에 대해 알고 상황에 따라 적절하게 사용하는 것은 중요합니다.

상수를 사용할 때는 언제인가요?

상수를 사용해야 할 경우는 다음과 같습니다:

  1. 값을 여러 곳에서 반복해서 사용해야 하는 경우
  2. 값을 한 번 정의하고 변경하지 않아야 하는 경우
  3. 코드를 더 읽기 쉽게 만들어야 하는 경우
  4. 논리적으로 상수로 인식되는 값을 나타내야 하는 경우

값이 한 번 선언되고 변경되지 않아야 하기 때문에, 상수는 변하지 않는 데이터를 표현하는 데 사용됩니다. 이러한 값은 프로그램의 여러 부분에서 공유되어야 하며, 일반적으로 여러 곳에서 읽기만 하는 용도로 사용됩니다.

상수를 사용하여 코드의 가독성과 유지 보수성을 향상시킬 수 있습니다. 상수는 프로그래밍에서 중요한 개념이므로, 개발자로서 상수를 사용하는 방법과 그 이유를 이해하는 것이 중요합니다.

Python에서 상수 정의하기

Python에는 상수를 정의하기 위한 특별한 구문이 없지만, 네이밍 컨벤션을 사용하여 개발자에게 상수로 사용되는 변수임을 알릴 수 있습니다. 일반적으로 Python 커뮤니티는 모든 문자가 대문자인 변수를 상수로 사용하는 것을 권장합니다.

Python에서 상수를 정의하는 다양한 방법을 알아보겠습니다.

사용자 정의 상수

Python에서 정의한 사용자 정의 변수는 대부분 상수로 취급됩니다. 그러므로 사용자가 변수명을 모두 대문자로 작성하기만 하면 상수를 표현할 수 있습니다. 그러나 이 값은 여전히 변경 가능한 변수이므로 사용자가 값을 변경할 수 있습니다.

MAX_CONNECTIONS = 10
API_KEY = "abcdefg"

이렇게 사용자 정의한 상수로 사용되는 변수는 변경되지 않아야 하므로 주의해야 합니다. 개발자들 사이에서 대문자로 작성된 변수를 일반적으로 상수로 사용하면서 값이 변경되지 않아야 한다는 암묵적인 약속이 있는데, 이 약속을 지키지 않으면 코드의 가독성과 유지 보수성에 문제가 발생할 수 있습니다.

모듈 수준의 던더 상수

또 다른 방법으로는 모듈 수준의 던더 상수를 사용하는 것입니다. 던더 상수는 이중 밑줄(__)로 시작하고 던더(__)로 끝나는 변수입니다. 이러한 던더 상수는 해당 모듈에서만 사용되어야 하며, 값을 변경하거나 재할당할 수 없습니다. 일반적으로 이러한 상수는 _CONSTANT_NAME 형식으로 작성됩니다.

다음은 math 모듈에서 사용되는 몇 가지 예시입니다:

import math
math.pi # 원주율
math.inf # 무한대
math.nan # NaN (Not a Number)

이러한 모듈 수준의 던더 상수는 Python에서 제공하는 표준 라이브러리에서 자주 사용됩니다. 이러한 상수는 변경되지 않는 값을 나타내므로, 해당 값은 프로그램의 여러 부분에서 공유되고 재사용될 수 있습니다.

상수 활용하기

이제 Python에서 상수를 활용하는 방법을 살펴보겠습니다. 상수는 프로그램의 여러 가지 측면에서 사용될 수 있습니다. 다음은 몇 가지 예시입니다:

가독성을 위해 매직 넘버 대체하기

매직 넘버(magic number)는 하드 코딩된 구체적인 값을 말합니다. 매직 넘버는 코드를 이해하기 어렵게 만들고, 필요한 값이 변경되는 경우 많은 수정 작업을 요구합니다.

이러한 매직 넘버를 상수로 대체하면 코드의 가독성이 향상됩니다. 상수 이름은 해당 값의 의미를 명확하게 나타내야 합니다. 이렇게 하면 코드를 처음 읽거나 다른 개발자가 코드를 검토할 때 해당 값의 목적을 이해하기 쉬워집니다.

다음은 매직 넘버를 대체한 상수를 사용하는 예시입니다:

# 매직 넘버를 사용한 예
radius = 5
area = 3.14159 * radius * radius
# 상수를 사용한 예
PI = 3.14159
radius = 5
area = PI * radius * radius

이렇게 상수를 사용하면 코드가 더 가독성이 높아지고, 값을 의미하는 이름으로 식별할 수 있습니다.

유지 보수성을 위해 객체 재사용하기

코드의 재사용성을 높이기 위해 동일한 값을 여러 번 사용하는 경우, 상수를 사용하여 일관성을 유지할 수 있습니다.

예를 들어, 다음과 같이 오래 걸리는 작업을 하는 함수가 있다고 가정해 봅시다:

import time
def process_data(data):
# DAILY_LIMIT: 하루에 처리할 수 있는 최대 데이터 양
DAILY_LIMIT = 100
# 데이터 처리 작업 수행
for i in range(DAILY_LIMIT):
time.sleep(1)
print(f"Processing data {i+1}/{DAILY_LIMIT}")
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] # 데이터
process_data(data)

위의 코드에서 DAILY_LIMIT는 하루에 처리할 수 있는 최대 데이터 양을 나타내는 상수입니다. 이러한 상수를 사용하여 코드가 일관된 동작을 유지하고 일관된 제한을 유지할 수 있습니다. 이렇게 코드의 각 인스턴스에서 동일한 상수를 사용하면 유지 보수 작업이 더 쉬워집니다.

또한, 상수를 사용하여 코드가 대개 변경되는 값과 분리되기 때문에, 값이 변경되더라도 상수만 업데이트하면 되므로 변경 작업이 간소화됩니다.

기본 인수 값 제공하기

Python 함수에서 인수의 기본 값을 지정할 수 있습니다. 이러한 기본 인수 값을 상수로 정의하면 코드의 가독성이 향상됩니다.

# 기본 인수 값으로 상수 사용하기
def calculate_area(radius, pi=3.14159):
return pi * radius * radius

위의 예시에서 calculate_area 함수는 radiuspi라는 두 개의 인수를 받습니다. pi 인수는 기본값으로 3.14159를 가집니다. 이를 통해 pi 값이 지정되지 않은 경우 3.14159를 사용하도록 설정할 수 있습니다. 이렇게 하면 코드가 더 명확하게 읽히고, 기본값을 변경하고자 할 때 일괄적으로 수정할 수 있습니다.

실제 프로젝트에서의 상수 처리

이제 실제 프로젝트에서 상수를 처리하는 방법을 알아보겠습니다. 상수를 사용하기 위해서는 적절한 구성과 관리 방식이 필요합니다. 다음은 프로젝트에서 상수를 처리하는 몇 가지 방법입니다:

관련 코드와 함께 상수 사용하기

관련된 코드와 함께 상수를 그룹화하면 코드의 가독성이 향상됩니다. 따라서 동일한 상수를 사용하는 코드 영역을 함께 그룹화하여 상수의 용도와 의미를 더 명확하게 전달할 수 있습니다.

# 코드 영역과 함께 상수 사용하기
MAX_CONNECTIONS = 10
TIMEOUT = 60
RETRY_LIMIT = 3
# 코드 작성
...

이렇게 함께 상수를 사용하면 프로젝트에서 여러 곳에서 동일한 상수를 사용하는 경우 해당 상수의 목적과 의미를 이해하기 쉬워집니다.

상수를 위한 전용 모듈 작성하기

여러 상수를 한 곳에서 관리하기 위해 전용 모듈을 작성할 수 있습니다. 이 모듈에는 상수만 포함되어 있으며, 다른 코드에서 이 모듈을 가져와 상수를 사용할 수 있습니다.

# constants.py 파일
MAX_CONNECTIONS = 10
TIMEOUT = 60
RETRY_LIMIT = 3
# main.py 파일
import constants
print(constants.MAX_CONNECTIONS)
print(constants.TIMEOUT)
print(constants.RETRY_LIMIT)

이러한 접근 방식을 사용하면 상수를 효율적으로 관리할 수 있으며, 코드의 유지 보수성이 향상됩니다. 상수를 전용 모듈에 작성하여 코드가 읽기 쉽고 관리하기 쉬운 상태를 유지할 수 있습니다.

구성 파일에 상수 저장하기

프로젝트에서 사용되는 상수를 문서화하고, 관리하기 편하게 저장하기 위해 구성 파일을 사용할 수 있습니다. 구성 파일은 별도의 파일로 상수를 저장하고, 코드에서는 이 파일에서 상수 값을 읽어와 사용할 수 있습니다.

YAML, JSON, INI 등 다양한 형식으로 구성 파일을 작성할 수 있으며, 프로젝트에서 사용하는 값에 가장 적합한 형식을 선택할 수 있습니다. 아래는 YAML 형식으로 작성된 config.yml 파일의 예입니다:

# config.yml 파일
MAX_CONNECTIONS: 10
TIMEOUT: 60
RETRY_LIMIT: 3
# main.py 파일
import yaml
with open("config.yml", "r") as file:
config = yaml.safe_load(file)
print(config["MAX_CONNECTIONS"])
print(config["TIMEOUT"])
print(config["RETRY_LIMIT"])

이러한 접근 방식을 사용하면 프로젝트에서 사용되는 상수를 관리하기가 훨씬 쉬워집니다. 상수를 구성 파일에 저장하여 값을 문서화하고, 코드에서 쉽게 업데이트하고, 여러 곳에서 공유할 수 있습니다.

환경 변수로 상수 처리하기

프로젝트의 보안 및 설정 정보와 같은 중요한 값은 환경 변수에 저장하는 것이 일반적입니다. 환경 변수는 운영체제 수준 또는 컨테이너 환경에서 정의되며, 프로그램의 여러 부분에서 액세스할 수 있습니다.

Python에서는 os 모듈을 사용하여 환경 변수에 액세스할 수 있습니다.

import os
MAX_CONNECTIONS = int(os.environ.get("MAX_CONNECTIONS", 10))
TIMEOUT = int(os.environ.get("TIMEOUT", 60))
RETRY_LIMIT = int(os.environ.get("RETRY_LIMIT", 3))

환경 변수에 값을 지정한 후, Python에서 이 값을 읽어와 상수로 사용할 수 있습니다. 이러한 접근 방식을 사용하면 프로젝트에서 중요한 값에 쉽게 액세스할 수 있습니다.

Python의 다른 상수 탐색하기

Python에서는 많은 내장 상수가 제공됩니다. 이러한 상수는 Python의 표준 라이브러리에서 사용됩니다.

내장 상수의 예시는 다음과 같습니다:

import math
print(math.pi) # 원주율
print(math.e) # 자연 상수 e

앞에서 언급한 것처럼, 내장 상수는 Python 표준 라이브러리의 다양한 모듈에서 사용됩니다. 이러한 상수는 Python의 핵심 기능을 제공하거나 수학 계산과 관련된 작업에 유용한 값들입니다. 모듈에 따라 제공되는 상수의 목록과 의미는 공식 문서를 참조하십시오.

상수 주석하기

파이썬 3.6부터는 **타입 힌트(type hint)**가 도입되었습니다. 이를 사용하면 변수의 타입을 명시적으로 지정할 수 있습니다. 타입 힌트는 사람과 도구에게 코드의 의도를 명확하게 전달합니다.

Python에서 상수에 타입 힌트를 사용하여 상수의 타입을 명시적으로 지정할 수 있습니다. 이렇게 하면 코드에서 상수를 사용하는 방식에 대해 문서화할 수 있으며, 가독성을 향상시키고, 잠재적인 버그를 방지할 수 있습니다.

다음은 MAX_CONNECTIONS 상수에 타입 힌트를 사용하는 예시입니다:

MAX_CONNECTIONS: int = 10

이러한 타입 힌트는 코드 리더와 툴에게 상수의 의도를 전달하고, 타입 체크를 통해 오류를 방지하는 데 도움이 됩니다.

Python에서 엄격한 상수 정의하기

Python에서는 상수의 값을 변경하거나 재할당하는 것을 방지하는 다양한 기법을 사용할 수 있습니다. 이러한 기법은 문자열, 리스트, 딕셔너리 등의 데이터 구조뿐만 아니라 클래스 객체에도 적용될 수 있습니다. 다음은 Python에서 엄격한 상수 정의를 위해 사용할 수 있는 몇 가지 기법입니다:

.__slots__ 속성

.__slots__ 속성은 클래스에서 사용할 수 있는 인스턴스 속성의 이름을 지정하는 특수한 속성입니다. 이 속성을 사용하면 클래스의 인스턴스에 추가 속성을 동적으로 할당하는 것을 방지할 수 있습니다.

class Constants:
__slots__ = ["MAX_CONNECTIONS", "TIMEOUT", "RETRY_LIMIT"]
MAX_CONNECTIONS = 10
TIMEOUT = 60
RETRY_LIMIT = 3

위의 예시에서 Constants 클래스는 MAX_CONNECTIONS, TIMEOUT, RETRY_LIMIT이라는 상수를 가지고 있습니다. 클래스 인스턴스에 추가 속성을 할당하는 것을 방지하기 위해 .__slots__ 속성에 상수의 이름을 명시적으로 지정해야 합니다.

@property 데코레이터

@property 데코레이터는 클래스의 메서드를 속성처럼 사용할 수 있도록 해줍니다. 이를 사용하면 속성 값을 직접 수정하거나 재할당하는 것을 방지할 수 있습니다.

class Constants:
MAX_CONNECTIONS = 10
TIMEOUT = 60
RETRY_LIMIT = 3
@property
def max_connections(self):
return self.MAX_CONNECTIONS
@property
def timeout(self):
return self.TIMEOUT
@property
def retry_limit(self):
return self.RETRY_LIMIT

위의 예시에서 max_connections, timeout, retry_limit은 메서드처럼 작성되지만, 속성처럼 사용할 수 있습니다. 따라서 이러한 속성 값을 직접 변경하거나 재할당하는 것은 허용되지 않습니다.

namedtuple() 팩토리 함수

namedtuple()은 튜플에 이름을 지정하는 팩토리 함수입니다. 이 함수를 사용하여 불변의 데이터 구조를 생성하는 것이 가능하며, 내부의 값을 변경하거나 재할당하는 것은 방지됩니다.

from collections import namedtuple
Constants = namedtuple("Constants", ["MAX_CONNECTIONS", "TIMEOUT", "RETRY_LIMIT"])
constants = Constants(10, 60, 3)
print(constants.MAX_CONNECTIONS)

위의 예시에서 Constants는 이름이 지정된 튜플을 생성하는 데 사용되며, 이 튜플의 속성 값은 변경되지 않습니다.

@dataclass 데코레이터

@dataclass 데코레이터는 데이터 클래스를 생성하는 데 사용됩니다. 데이터 클래스는 데이터를 저장하기 위한 클래스이며, 상수 값을 포함할 수도 있습니다. 데이터 클래스를 사용하면 클래스의 속성 값을 변경하는 것을 방지할 수 있습니다.

from dataclasses import dataclass
@dataclass(frozen=True)
class Constants:
MAX_CONNECTIONS: int = 10
TIMEOUT: int = 60
RETRY_LIMIT: int = 3

위의 예시에서 @dataclass(frozen=True)는 데이터 클래스를 생성하고, frozen=True 옵션은 데이터 객체의 속성 값을 변경하는 것을 방지합니다.

.__setattr__() 특수 메서드

.__setattr__() 특수 메서드를 사용하여 클래스의 속성 값 변경을 제어할 수 있습니다. 이 매직 메서드를 오버라이딩하면 클래스의 속성 값을 변경하는 것이 막히게 됩니다.

class Constants:
MAX_CONNECTIONS = 10
TIMEOUT = 60
RETRY_LIMIT = 3
def __setattr__(self, name, value):
raise TypeError("Can't modify constants")

위의 예시에서 __setattr__() 특수 메서드를 오버라이딩하여, 속성 값을 변경하려는 경우 TypeError가 발생하도록 설정합니다. 이로써 클래스의 상수 값을 변경하는 것을 방지할 수 있습니다.

결론

상수는 프로그램의 실행 동안 변경되지 않는 값을 나타내는 중요한 개념입니다. Python에서는 상수를 변수로 표현하며, 이름을 대문자로 작성하여 사용합니다. 상수는 코드의 가독성, 재사용성 및 유지 보수성을 향상시키는 데 큰 도움이 됩니다.

이 튜토리얼에서는 Python에서 상수를 정의하고 사용하는 방법에 대해 배웠습니다. 또한, 상수를 관리하고 구성하는 몇 가지 방식도 살펴보았습니다. 개발자로서 상수를 적절하게 활용하는 것은 코드의 품질과 유지 보수성을 향상시키는 데 큰 기여를 할 수 있습니다.

Python에서는 다양한 기법을 사용하여 엄격한 상수 정의를 할 수 있습니다. 이런 기법들을 활용하여 상수의 값을 변경하는 것을 방지하고, 코드의 안정성을 향상시킬 수 있습니다.

Python에서 상수를 사용하여 코드의 유지 보수성을 개선하고 가독성과 재사용성을 높일 수 있습니다. Python 개발자로서, 마지막으로 언급한 다양한 상수 정의 기법을 사용하여 코드를 개선하고, 상황에 맞는 적절한 상수 사용법을 익히는 것이 중요합니다.