source

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

nicesource 2023. 7. 18. 21:47
반응형

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

저는 두 부분으로 구성된 작은 파이썬 모듈을 코딩하고 있습니다.

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

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

그렇다면, 코멘트와 문서 문자열 외에도, 클래스를 "개인" 또는 "내부"로 표시하는 메커니즘이 있습니까?밑줄 메커니즘은 알고 있지만, 제가 알기로는 변수, 함수 및 메서드 이름에만 적용됩니다.

단일 밑줄 접두사 사용:

class _Internal:
    ...

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

단일 밑줄 규칙에 대한 참조입니다.

간단히 말해서:

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

  2. 개인 정보만 표시/제안할 수 있습니다.이것은 관례에 따른 것입니다.클래스/함수/메소드를 비공개로 표시하는 Python 규약은 _(밑줄)로 앞에 붙입니다.예를들면,def _myfunc()또는class _MyClass: 앞에 두 개의 메드앞 에두 개밑붙예유여개생정수성할있도습다니를보사인을줄)을 붙여 개인 정보 를 만들 .__foo). 액세스할 이름을 접두사를 할 수는 . . 메 에 직 액 예 없 사 메 통 를 서 드 호 수 출 할 는 있 습 니 다 해 사 접 를 서 :_classname__foo할 수 방법은 사생활을 표시/하는 것이 아닙니다 따라서 개인 정보 보호를 강제하는 것이 아니라 개인 정보를 표시/제안하는 것이 최선입니다.

Python은 이 점에서 Perl과 같습니다.펄 책에서 사생활에 관한 유명한 구절을 인용하자면, 그 철학은 여러분이 거실에 있지 않아야 한다는 것입니다. 왜냐하면 여러분은 초대받지 않았기 때문이지 산탄총으로 보호되었기 때문이 아닙니다.

자세한 정보:

__all__내보낼 이름 목록입니다(설명서 참조).

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

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

클래스 정의:

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

클래스 이름을 덮어쓰는 클래스의 인스턴스를 만듭니다.

x = x()

기능을 노출하는 기호를 정의합니다.

doThis = x.doThis
doThat = x.doThat

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

del x

이제 공개 기능만 공개하는 모듈이 있습니다.

규칙은 내부 클래스, 함수 및 변수 앞에 "_"을 붙입니다.

설계 규칙 문제를 해결하기 위해, 그리고 슈뢰더가 말했듯이, 파이썬에는 "프라이빗"과 같은 것이 없습니다.C/C++ 배경(예를 들어 얼마 전의 저)에서 온 사람들에게는 이것이 왜곡된 것처럼 들릴 수 있지만, 결국에는 다음과 같은 관례로도 충분하다는 것을 깨닫게 될 것입니다.

앞에 밑줄이 있는 것을 보는 것은 그것을 직접적으로 사용하지 않기에 충분한 힌트가 될 것입니다.어수선함이 걱정된다면,help(MyClass)출력(클래스 사용 방법을 검색할 때 모두가 보는 것), 밑줄 친 특성/키워드는 여기에 포함되지 않으므로 "공개" 인터페이스에 대한 설명만 하게 됩니다.

또한 모든 것을 공개하는 것은 자체적으로 놀라운 특전을 가지고 있습니다. 예를 들어, 외부에서 거의 모든 것을 유닛 테스트할 수 있습니다(C/C++ 프라이빗 구성으로는 실제로 할 수 없습니다).

두 개의 밑줄을 사용하여 "개인" 식별자의 이름 앞에 붙입니다.모듈에 있는 클래스의 경우 선행 밑줄 하나를 사용하면 "모듈 가져오기 *"를 사용하여 가져올 수 없습니다.

class _MyInternalClass:
    def __my_private_method:
        pass

(Python에는 진정한 "프라이빗"이라는 것이 없습니다.예를 들어 Python은 클래스 멤버의 이름을 두 개의 밑줄로 자동으로 변환합니다.__clssname_mymember그래서 정말로, 만약 당신이 망가진 이름을 안다면, 당신은 어쨌든 "개인" 실체를 사용할 수 있습니다.여기 보세요.물론 원하는 경우 "내부" 클래스를 수동으로 가져올 수도 있습니다.

실제로 범위 지정을 통해 개인 회원과 유사한 것을 달성할 수 있습니다.클래스를 만드는 동안 새 로컬 범위 변수를 만드는 모듈 수준 클래스를 만든 다음 해당 클래스의 다른 곳에서 해당 변수를 사용할 수 있습니다.

class Foo:
    def __new__(cls: "type[Foo]", i: int, o: object) -> "Foo":
        _some_private_int: int = i
        _some_private_obj: object = o
        foo = super().__new__(cls)
        def show_vars() -> None:
            print(_some_private_int)
            print(_some_private_obj)
        foo.show_vars = show_vars
        return foo

    def show_vars(self: "Foo") -> None:
        pass

다음과 같은 작업을 수행할 수 있습니다.

foo = Foo(10, {"a":1})
foo.show_vars()
# 10
# {'a': 1}

또는 클래스가 생성되는 함수에 대한 범위가 지정된 변수에 액세스할 수 있는 모듈에 클래스를 만드는 잘못된 예가 있습니다.이 상태는 모든 인스턴스 간에 공유되므로 이 예를 주의하십시오.이것을 피할 수 있는 방법이 있을 거라고 확신합니다만, 그것은 다른 사람을 위한 운동으로 남겨두겠습니다.

def _foo_create():
    _some_private_int: int
    _some_private_obj: object
    class Foo:
        def __init__(self, i: int, o: object) -> None:
            nonlocal _some_private_int
            nonlocal _some_private_obj
            _some_private_int = i
            _some_private_obj = o

        def show_vars(self):
            print(_some_private_int)
            print(_some_private_obj)

    import sys
    sys.modules[__name__].Foo = Foo
_foo_create()

제가 아는 한, 이러한 로컬 범위 변수에 액세스할 수 있는 방법은 없지만, 가능하다면 다른 방법을 알고 싶습니다.

저는 파이썬에 익숙하지 않지만, 제가 알기로는 파이썬은 자바와 같지 않습니다.다음은 Python에서 발생하는 방법입니다.

class Student:

    __schoolName = 'XYZ School'      # private attribute
    def __nameprivamethod(self):     # private function 
         print('two underscore')

class Student:

    _schoolName = 'XYZ School'       # protected attribute

개인 및 보호된 부분에 액세스하는 방법을 확인하지 마십시오.

언급URL : https://stackoverflow.com/questions/551038/private-implementation-class-in-python

반응형