Python의 "Private"(구현) 클래스


106

두 부분으로 구성된 작은 Python 모듈을 코딩하고 있습니다.

  • 공용 인터페이스를 정의하는 일부 함수,
  • 위 함수에서 사용하는 구현 클래스이지만 모듈 외부에서는 의미가 없습니다.

처음에는이 구현 클래스를 사용하는 함수 내부에 정의하여 "숨기기"로 결정했지만 이로 인해 가독성이 떨어지고 여러 함수가 동일한 클래스를 재사용하는 경우 사용할 수 없습니다.

그래서 주석과 독 스트링 외에도 클래스를 "비공개"또는 "내부"로 표시하는 메커니즘이 있습니까? 밑줄 메커니즘을 알고 있지만 이해하기 때문에 변수, 함수 및 메서드 이름에만 적용됩니다.

답변:


174

단일 밑줄 접두사를 사용합니다.

class _Internal:
    ...

이것은 '내부'기호에 대한 공식 파이썬 규칙입니다. "from module import *"는 밑줄 접두사가 붙은 개체를 가져 오지 않습니다.

편집 : 단일 밑줄 규칙 에 대한 참조


3
클래스에 확장 된 밑줄 규칙을 몰랐습니다. 가져올 때 네임 스페이스를 복잡하게 만들고 싶지 않으므로이 동작이 제가 찾고 있던 것입니다. 감사!
oparisy

1
이것이 "공식적인"파이썬 규칙이라고 말 했으므로 링크가 있으면 좋을 것입니다. 여기에 또 다른 게시물은 모든 것이 공식적인 방법이며 문서에 대한 링크를 제공 한다고 말합니다 .
flodin

11
python.org/dev/peps/pep-0008-_single_leading_underscore : 약한 "내부 사용"표시기. 예를 들어 "from M import *"는 이름이 밑줄로 시작하는 개체를 가져 오지 않습니다. -내부 용 클래스에는 밑줄이 앞에 표시됩니다.
Miles

2
앞선 밑줄은 "이것을 엉망으로 만들지 마십시오"라는 것을 내부로 표시하는 규칙입니다. 반면 모든 것은 모듈 사용자가 만져서는 안된다는 의미없이 "from M import *"와 함께 사용하도록 설계된 모듈에 대한 것입니다. 그 수업.
Miles

65

요컨대 :

  1. 개인 정보를 보호 할 수 없습니다 . Python에는 비공개 클래스 / 메서드 / 함수가 없습니다. 적어도 Java와 같은 다른 언어 에서처럼 엄격한 개인 정보 보호는 아닙니다.

  2. 개인 정보 보호만을 표시 / 제안 할 수 있습니다 . 이것은 관례를 따릅니다. 클래스 / 함수 / 메서드를 비공개로 표시하는 파이썬 규칙은 앞에 _ (밑줄)을 붙이는 것입니다. 예를 들어, def _myfunc()또는 class _MyClass:. 또한 두 개의 밑줄 (예 :)을 사용하여 메서드를 시작하여 의사 개인 정보를 만들 수도 있습니다 __foo. 메서드에 직접 액세스 할 수는 없지만 클래스 이름 (예 :)을 사용하는 특수 접두사를 통해 여전히 호출 할 수 있습니다 _classname__foo. 따라서 귀하가 할 수있는 최선은 개인 정보 보호를 강요하는 것이 아니라 표시 / 제안하는 것입니다.

파이썬은이 점에서 펄과 같습니다. Perl 책에서 프라이버시에 관한 유명한 대사를 바꿔 말하면, 철학은 당신이 초대받지 않았기 때문에 거실에서 나가야한다는 것입니다.

자세한 내용은:


# 1에 대한 응답으로 메서드의 개인 정보를 적용 할 수 있습니다. __method (self)와 같은 이중 밑줄을 사용하면 클래스 외부에서 액세스 할 수 없게됩니다. 그러나 Foo () ._ Foo__method ()와 같이 호출하는 방법이 있습니다. 나는 그것이 더 난해한 것으로 이름을 바꾼 것 같습니다.
Evan Fosmark

1
그 인용문은 정확합니다.
Paul Draper

37

__all__내보낼 이름 목록 인을 정의합니다 ( 문서 참조 ).

__all__ = ['public_class'] # don't add here the 'implementation_class'

10

내가 가끔 사용하는 패턴은 다음과 같습니다.

클래스 정의 :

class x(object):
    def doThis(self):
        ...
    def doThat(self):
        ...

클래스의 인스턴스를 만들고 클래스 이름을 덮어 씁니다.

x = x()

기능을 노출하는 기호를 정의하십시오.

doThis = x.doThis
doThat = x.doThat

인스턴스 자체를 삭제합니다.

del x

이제 공용 함수 만 노출하는 모듈이 있습니다.


2
"클래스 이름 덮어 쓰기"의 목적 / 기능을 이해하는 데 잠시 시간이 걸렸지 만 그렇게했을 때 큰 웃음을 느꼈습니다. 언제 사용할지 모르겠습니다. :)
Zach Young

이 기술의 이름이 있습니까?
Bishwas Mishra


4

디자인 관습의 문제를 다루기 위해 크리스토퍼가 말했듯이 파이썬에는 "비공개"와 같은 것이 없습니다. 이것은 C / C ++ 배경에서 온 누군가에게는 왜곡 된 것처럼 들릴 수 있지만 (예를 들어, 저처럼) 결국에는 다음 규칙이 충분하다는 것을 알게 될 것입니다.

앞에 밑줄이있는 것을 보는 것은 그것을 직접 사용하지 않기에 충분한 힌트가 될 것입니다. 복잡한 help(MyClass)출력 (모든 사람이 클래스 사용 방법을 검색 할 때 보는 것임)에 관심이 있다면 밑줄이있는 속성 / 클래스가 여기에 포함되지 않으므로 "공용"인터페이스 만 설명하게됩니다.

또한 모든 것을 공개하는 것은 그 자체로 멋진 특전을 가지고 있습니다. 예를 들어 외부에서 거의 모든 것을 단위 테스트 할 수 있습니다 (C / C ++ 비공개 구문으로는 실제로 할 수 없음).


4

"개인"식별자의 이름 앞에 두 개의 밑줄을 사용합니다. 모듈의 클래스의 경우 단일 선행 밑줄을 사용하고 "from module import *"를 사용하여 가져 오지 않습니다.

class _MyInternalClass:
    def __my_private_method:
        pass

(Python에는 진정한 "private"와 같은 것은 없습니다. 예를 들어, Python은 자동으로 이중 밑줄이있는 클래스 멤버의 이름을으로 변경합니다 __clssname_mymember. 따라서 변경된 이름을 알고 있다면 어쨌든 "private"엔티티를 사용할 수 있습니다. . 여기를 참조하십시오. 물론 원하는 경우 "내부"클래스를 수동으로 가져 오도록 선택할 수 있습니다.


왜 _가 두 개입니까? 하나면 충분합니다.
S.Lott

"가져 오기"에서 클래스와 함수를 가져 오지 못하도록하려면 밑줄 하나만 있으면됩니다. Python의 이름 변경 기능을 사용하려면 두 개의 밑줄이 필요합니다. 더 명확해야했습니다. 나는 편집했다.
chroder

이제 후속 조치입니다. 이름 맹 글링이 필요한 이유는 무엇입니까? 그것의 가능한 이점은 무엇입니까?
S.Lott

5
가능한 이점은 이러한 변수에 액세스해야하는 다른 개발자를 짜증나게하는 것입니다. :)
Richard Levasseur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.