문제

Python에서는 다음과 같이 이름 앞에 이중 밑줄을 추가하여 클래스 내에서 '비공개' 메서드와 변수를 생성할 수 있는 기능을 제공합니다. __myPrivateMethod().그렇다면 이것을 어떻게 설명할 수 있는가?

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!

무슨 일이야?!

이해가 잘 안가시는 분들을 위해 조금 설명드리겠습니다.

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

거기서 내가 한 일은 공개 메소드와 비공개 메소드로 클래스를 생성하고 인스턴스화하는 것이었습니다.

다음으로 공개 메서드를 호출합니다.

>>> obj.myPublicMethod()
public method

다음으로 개인 메서드를 호출해 봅니다.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

여기에서는 모든 것이 좋아 보입니다.우리는 그것을 부를 수 없습니다.엄밀히 말하면 '비공개'입니다.글쎄요, 실제로는 그렇지 않습니다.달리기 디렉토리() 객체에 대한 파이썬이 모든 '비공개' 메서드에 대해 마법처럼 생성하는 새로운 마법 메서드를 보여줍니다.

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

이 새로운 메소드의 이름은 항상 밑줄로 구성되며 그 뒤에 클래스 이름, 메소드 이름이 옵니다.

>>> obj._MyClass__myPrivateMethod()
this is private!!

캡슐화에는 너무 많죠?

어쨌든 저는 Python이 캡슐화를 지원하지 않는다는 말을 항상 들었는데, 왜 시도해 보겠습니까?무엇을 제공합니까?

도움이 되었습니까?

해결책

이름 스크램블링은 하위 클래스가 실수로 상위 클래스의 비공개 메서드와 속성을 재정의하지 않도록 하기 위해 사용됩니다.외부로부터의 고의적인 접근을 방지하도록 설계된 것은 아닙니다.

예를 들어:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

물론 두 개의 서로 다른 클래스가 동일한 이름을 갖는 경우에는 문제가 발생합니다.

다른 팁

비공개 기능의 예

import re
import inspect

class MyClass :

    def __init__(self) :
        pass

    def private_function ( self ) :
        try :
            function_call = inspect.stack()[1][4][0].strip()

            # See if the function_call has "self." in the begining
            matched = re.match( '^self\.', function_call )
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except :
            print 'This is Private Function, Go Away'
            return

        # This is the real Function, only accessible inside class #
        print 'Hey, Welcome in to function'

    def public_function ( self ) :
        # i can call private function from inside the class
        self.private_function()

### End ###

처음 Java에서 Python으로 넘어왔을 때 미움받는 이것.겁이 나서 죽을 지경이었습니다.

오늘은 그게 유일한 것일지도 몰라 나는 가장 사랑한다 파이썬에 대해서.

나는 사람들이 서로를 신뢰하고 코드 주위에 뚫을 수 없는 벽을 쌓을 필요가 없다고 느끼는 플랫폼에 있는 것을 좋아합니다.강력하게 캡슐화된 언어에서는 API에 버그가 있고 무엇이 잘못되었는지 알아낸 경우 필요한 메서드가 비공개이므로 여전히 문제를 해결하지 못할 수 있습니다.Python에서 태도는 다음과 같습니다."확신하는".상황을 이해했다고 생각하고 아마도 읽어보셨다면 우리가 말할 수 있는 것은 "행운을 빕니다!"입니다.

캡슐화는 "보안"이나 아이들을 잔디밭에서 멀리하는 것과도 약한 관련이 없다는 것을 기억하십시오.이는 코드 기반을 더 쉽게 이해하기 위해 사용해야 하는 또 다른 패턴일 뿐입니다.

에서 http://www.faqs.org/docs/diveintopython/fileinfo_private.html

엄격하게 말하면, 개인 방법은 수업 밖에서 액세스 할 수 있으며 쉽게 접근 할 수 없습니다.파이썬의 어떤 것도 진정으로 사적인 것이 아닙니다.내부적으로 개인 방법과 속성의 이름은 즉석에서 엉망이되고 방해가되지 않아 주어진 이름으로 접근 할 수없는 것처럼 보입니다._mp3fileinfo__parse라는 이름으로 mp3fileinfo 클래스의 __parse 메소드에 액세스 할 수 있습니다.이것이 흥미 롭다는 것을 인정하고, 결코 실제 코드로 그것을하지 않겠다고 약속하십시오.사적인 방법은 이유가 있기 때문에 사적인 방법이지만 파이썬의 다른 많은 것들과 마찬가지로 민간성은 궁극적으로 힘이 아닌 협약의 문제입니다.

일반적으로 사용되는 문구는 "여기서 우리는 모두 동의한 성인입니다"입니다.하나의 밑줄(노출하지 않음)이나 이중 밑줄(숨기기)을 앞에 추가하면 클래스 사용자에게 멤버가 어떤 방식으로든 '비공개'가 되도록 의도한다는 것을 알리는 것입니다.그러나 다른 모든 사람이 책임감 있게 행동하고 이를 존중할 것이라고 믿습니다(예:디버거, 코드 완성).

정말로 비공개적인 것이 있어야 한다면 확장 기능으로 구현할 수 있습니다(예:CPython의 경우 C).그러나 대부분의 경우 Python 방식으로 작업을 수행하는 것뿐입니다.

모든 언어(C++의 포인터 산술, .NET/Java의 Reflections)에서 멤버의 비공개성을 절대 피할 수 없는 것은 아닙니다.

요점은 실수로 개인 메서드를 호출하려고 하면 오류가 발생한다는 것입니다.하지만 자신의 발에 총을 쏘고 싶다면 계속해서 하십시오.

편집하다:OO 캡슐화로 물건을 보호하려고 하지 않습니까?

그만큼 class.__stuff 명명 규칙을 통해 프로그래머는 자신이 액세스할 의도가 없음을 알 수 있습니다. __stuff 밖에서.맹글링(mangling)이라는 이름을 사용하면 누구도 우연히 이를 수행할 가능성이 없습니다.

사실, 여전히 이 문제를 해결할 수 있습니다. 다른 언어보다 훨씬 쉽습니다(BTW에서도 이 작업을 수행할 수 있습니다). 그러나 캡슐화에 관심이 있다면 어떤 Python 프로그래머도 이 작업을 수행하지 않을 것입니다.

모듈 속성 이름이 단일 밑줄로 시작하는 경우에도 비슷한 동작이 발생합니다(예:_foo).

이와 같이 명명된 모듈 속성은 다음을 사용할 때 가져오기 모듈에 복사되지 않습니다. from* 방법, 예:

from bar import *

그러나 이는 관례일 뿐 언어 제약은 아닙니다.이는 개인 속성이 아닙니다.모든 수입업체가 참조하고 조작할 수 있습니다.어떤 사람들은 이 때문에 Python이 진정한 캡슐화를 구현할 수 없다고 주장합니다.

이는 언어 디자인 선택 중 하나일 뿐입니다.어떤 수준에서는 그것들이 정당화됩니다.그들은 메소드를 시도하고 호출하기 위해 꽤 먼 길을 가야하도록 만들고, 정말로 그렇게 심하게 필요하다면 꽤 그럴듯한 이유가 있어야합니다!

물론 책임감 있게 사용되는 가능한 애플리케이션으로 디버깅 후크와 테스트가 떠오릅니다.

Python 3.4에서는 다음과 같은 동작이 수행됩니다.

>>> class Foo:
        def __init__(self):
                pass
        def __privateMethod(self):
                return 3
        def invoke(self):
                return self.__privateMethod()


>>> help(Foo)
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  invoke(self)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

 >>> f = Foo()
 >>> f.invoke()
 3
 >>> f.__privateMethod()
 Traceback (most recent call last):
   File "<pyshell#47>", line 1, in <module>
     f.__privateMethod()
 AttributeError: 'Foo' object has no attribute '__privateMethod'

https://docs.python.org/3/tutorial/classes.html#tut-private

맹글링 규칙은 주로 사고를 방지하기 위해 설계되었습니다. 비공개로 간주되는 변수에 액세스하거나 수정하는 것은 여전히 ​​가능합니다. 이는 디버거와 같은 특별한 상황에서도 유용할 수 있습니다.

질문이 오래되었더라도 내 스니펫이 도움이 되기를 바랍니다.

비공개 메서드와 속성에 대한 가장 중요한 관심사는 개발자에게 클래스 외부에서 호출하지 말라고 지시하는 것입니다. 이것이 바로 캡슐화입니다.캡슐화로 인한 보안을 오해할 수도 있습니다.당신이 언급한 것과 같은 구문을 의도적으로 사용하는 경우 캡슐화를 원하지 않습니다.

obj._MyClass__myPrivateMethod()

저는 C#에서 마이그레이션했는데 처음에는 저에게도 이상했습니다. 그러나 잠시 후 Python 코드 디자이너가 OOP에 대해 생각하는 방식만 다르다는 생각에 이르렀습니다.

Python의 '비공개' 메소드가 실제로 비공개가 아닌 이유는 무엇입니까?

내가 이해하기로는 그들은 캔트 비공개로 유지하세요.개인 정보 보호는 어떻게 시행될 수 있나요?

분명한 대답은 "비공개 멤버는 다음을 통해서만 액세스할 수 있습니다. self"하지만 그건 작동하지 않을 것입니다. self Python에서는 특별한 것이 아니며 함수의 첫 번째 매개변수에 대해 일반적으로 사용되는 이름에 지나지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top