[python] 파이썬에서 상수를 어떻게 만듭니 까?

파이썬에서 상수를 선언하는 방법이 있습니까? Java에서는 다음과 같은 방법으로 상수 값을 만들 수 있습니다.

public static final String CONST_NAME = "Name";

파이썬에서 위의 Java 상수 선언에 해당하는 것은 무엇입니까?



답변

아니 없어. 파이썬에서는 변수 나 값을 상수로 선언 할 수 없습니다. 변경하지 마십시오.

수업에 참여하는 경우 다음과 같습니다.

class Foo(object):
    CONST_NAME = "Name"

그렇지 않다면, 그것은 단지

CONST_NAME = "Name"

그러나 Alex Martelli의 Python 의 코드 스 니펫 상수를 살펴볼 수 있습니다 .


Python 3.8 typing.Final부터는 변수를 다시 할당해서는 안된다는 정적 유형 검사기 (mypy와 같은)를 알려주 는 변수 주석이 있습니다. 이것은 Java와 가장 가까운 것 final입니다. 그러나 실제로 재 할당을 막지는 않습니다 .

from typing import Final

a: Final = 1

# Executes fine, but mypy will report an error if you run mypy on this:
a = 2


답변

더 없어 const다른 언어로 키워드, 그러나 재산권 만들 수 는 “게터 기능”이 데이터를 읽을 수있는,하지만 아니오 “setter 함수” 데이터를 다시 쓰기로한다. 이것은 본질적으로 식별자가 변경되는 것을 방지합니다.

다음은 클래스 속성을 사용하는 대체 구현입니다.

독자가 상수에 대해 궁금해하는 코드는 쉽지 않습니다. 아래 설명을 참조하십시오

def constant(f):
    def fset(self, value):
        raise TypeError
    def fget(self):
        return f()
    return property(fget, fset)

class _Const(object):
    @constant
    def FOO():
        return 0xBAADFACE
    @constant
    def BAR():
        return 0xDEADBEEF

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

코드 설명 :

  1. constant표현식을 취하는 함수 를 정의하고 이를 사용하여 표현식 값만 리턴하는 함수 인 “getter”를 구성하십시오.
  2. setter 함수는 TypeError를 일으켜 읽기 전용입니다.
  3. constant방금 만든 장식 기능을 사용하여 읽기 전용 속성을 빠르게 정의하십시오.

그리고 다른 구식 방법으로 :

(코드는 매우 까다 롭고 아래에 더 자세한 설명이 있습니다)

class _Const(object):
    @apply
    def FOO():
        def fset(self, value):
            raise TypeError
        def fget(self):
            return 0xBAADFACE
        return property(**locals())

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

@apply 데코레이터는 더 이상 사용되지 않는 것으로 보입니다.

  1. 식별자 FOO를 정의하기 위해 firs는 두 가지 함수를 정의합니다 (fset, fget-이름은 내가 선택했습니다).
  2. 그런 다음 내장 property함수를 사용하여 “설정”또는 “get”가능한 오브젝트를 구성하십시오.
  3. 참고 모자는 property함수의 처음 두 매개 변수의 이름은 fset하고 fget.
  4. 우리가 getter & setter에 대해 이러한 이름을 선택했다는 사실을 사용하고 매개 변수를 property함수에 전달하기 위해 해당 범위의 모든 로컬 정의에 ** (이중 별표)를 사용하여 키워드 사전을 만듭니다.

답변

파이썬은 무언가를 적용하는 언어 대신 __method개인 메소드와 _method보호 메소드에 대한 명명 규칙을 사용 합니다.

따라서 같은 방식으로 상수를 모든 대문자로 선언 할 수 있습니다.

MY_CONSTANT = "one"

이 상수가 절대 변경되지 않게하려면 속성 액세스에 연결하여 트릭을 수행 할 수 있지만 더 간단한 방법은 함수를 선언하는 것입니다.

def MY_CONSTANT():
    return "one"

문제는 어디에서나 MY_CONSTANT ()를 수행해야하지만 어디서나 MY_CONSTANT = "one"파이썬에서 올바른 방법입니다 (일반적으로).

명명 된 튜플 을 사용하여 상수를 만들 수도 있습니다 .

>>> from collections import namedtuple
>>> Constants = namedtuple('Constants', ['pi', 'e'])
>>> constants = Constants(3.14, 2.718)
>>> constants.pi
3.14
>>> constants.pi = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute


답변

최근에 의미있는 오류 메시지를 자동으로 발생시키고 __dict__다음을 통한 액세스를 방지하는 매우 간결한 업데이트를 발견했습니다 .

class CONST(object):
    __slots__ = ()
    FOO = 1234

CONST = CONST()

# ----------

print(CONST.FOO)    # 1234

CONST.FOO = 4321              # AttributeError: 'CONST' object attribute 'FOO' is read-only
CONST.__dict__['FOO'] = 4321  # AttributeError: 'CONST' object has no attribute '__dict__'
CONST.BAR = 5678              # AttributeError: 'CONST' object has no attribute 'BAR'

우리는 스스로를 인스턴스로 만들고 슬롯을 사용하여 추가 속성을 추가 할 수 없도록 정의합니다. 또한 __dict__액세스 경로가 제거 됩니다. 물론 전체 개체를 여전히 재정의 할 수 있습니다.

편집-원래 솔루션

아마도 여기에 트릭이 누락되었지만 이것이 나를 위해 작동하는 것 같습니다.

class CONST(object):
    FOO = 1234

    def __setattr__(self, *_):
        pass

CONST = CONST()

#----------

print CONST.FOO    # 1234

CONST.FOO = 4321
CONST.BAR = 5678

print CONST.FOO    # Still 1234!
print CONST.BAR    # Oops AttributeError

인스턴스를 생성하면 매직 __setattr__메소드가 FOO변수 설정을 시도하고 가로 챌 수 있습니다. 원한다면 여기에서 예외를 던질 수 있습니다. 클래스 이름으로 인스턴스를 인스턴스화하면 클래스를 통해 직접 액세스 할 수 없습니다.

하나의 가치에 대한 총 고통이지만 CONST객체 에 많은 것을 붙일 수 있습니다 . 상류층이 있으면 클래스 이름도 약간 거칠어 보이지만 전체적으로 간결하다고 생각합니다.


답변

파이썬에는 상수가 없습니다.

아마도 가장 쉬운 대안은 함수를 정의하는 것입니다.

def MY_CONSTANT():
    return 42

MY_CONSTANT() 이제 상수의 모든 기능을 갖추고 있습니다 (성가신 괄호).


답변

UPPERCASE 이름을 가진 변수를 사용하거나 속성을 사용하여 값을 읽기 전용으로 만드는 두 가지 최고의 답변 외에도 명명 된 상수 를 구현하기 위해 메타 클래스를 사용할 수 있다고 언급하고 싶습니다 . GitHub 에서 메타 클래스를 사용하는 매우 간단한 솔루션을 제공합니다 .

>>> from named_constants import Constants
>>> class Colors(Constants):
...     black = 0
...     red = 1
...     white = 15
...
>>> c = Colors.black
>>> c == 0
True
>>> c
Colors.black
>>> c.name()
'black'
>>> Colors(0) is c
True

이것은 약간 고급 파이썬이지만 여전히 사용하기 쉽고 편리합니다. (이 모듈에는 읽기 전용 상수를 포함하여 더 많은 기능이 있으며 README를 참조하십시오.)

다양한 저장소에 떠 다니는 비슷한 솔루션이 있지만, 내가 아는 한, 상수 (예 : 상수 또는 임의 유형)에서 기대할 수있는 기본 기능 중 하나가 부족하거나 밀교 기능이 추가되었습니다. 덜 일반적으로 적용하십시오. 그러나 YMMV, 피드백에 감사드립니다. 🙂


답변

속성은 상수를 만드는 한 가지 방법입니다. getter 속성을 선언하지만 setter를 무시하면됩니다. 예를 들면 다음과 같습니다.

class MyFinalProperty(object):

    @property
    def name(self):
        return "John"

파이썬 속성을 사용하는 더 많은 방법을 찾기 위해 작성한 기사를 살펴볼 수 있습니다 .