[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 () 을 실행 하면 파이썬이 모든 ‘비공개’메소드에 대해 마술처럼 만드는 새로운 마법 메소드가 나타납니다.

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

이 새로운 메소드의 이름은 항상 밑줄, 클래스 이름, 메소드 이름입니다.

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

캡슐화에 너무 많은, 응?

어쨌든, 나는 항상 파이썬이 캡슐화를 지원하지 않는다고 들었습니다. 무엇을 제공합니까?



답변

이름 스크램블링은 서브 클래스가 실수로 수퍼 클래스의 전용 메소드 및 속성을 대체하지 않도록하기 위해 사용됩니다. 외부에서 의도적으로 액세스하지 못하도록 설계되지 않았습니다.

예를 들면 다음과 같습니다.

>>> 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에 버그가 있고 무엇이 잘못되었는지 파악한 경우 필요한 메소드가 비공개이기 때문에 여전히 문제를 해결할 수 없습니다. 파이썬에서 태도는 “확실히”입니다. 당신이 상황을 이해한다고 생각한다면, 아마도 당신은 그것을 읽었을 것입니다. 우리가 말할 수있는 것은 “행운입니다!”입니다.

캡슐화는 “보안”이나 아이들을 잔디밭에 두지 않는 것과 관련이 없습니다. 코드 기반을 이해하기 쉽도록 사용해야하는 또 다른 패턴 일뿐입니다.


답변

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

엄밀히 말하면 개인 메소드는 클래스 외부에서 액세스 할 수 있으며 쉽게 액세스 할 수는 없습니다. 파이썬에는 아무것도 사적인 것이 없습니다. 내부적으로, 개인 메소드 및 속성의 이름은 지정된 이름으로 액세스 할 수없는 것처럼 보이게하기 위해 엉망이되어 있습니다. _MP3FileInfo__parse 이름으로 MP3FileInfo 클래스의 __parse 메소드에 액세스 할 수 있습니다. 이것이 흥미 롭다는 것을 인정하고 실제 코드에서는 절대로 그렇게하지 않겠다고 약속하십시오. 개인 메소드는 사적인 이유로 비공개이지만, 파이썬의 다른 많은 것들과 마찬가지로, 개인의 사유는 결국 강제가 아니라 관습의 문제입니다.


답변

일반적으로 사용되는 문구는 “우리는 모두 동의하는 성인입니다”입니다. 단일 밑줄 (노출하지 않음) 또는 이중 밑줄 (숨기기)을 앞에 추가하면 클래스 사용자에게 멤버가 어떤 식 으로든 ‘비공개’가 되겠다고 알려줍니다. 그러나 다른 모든 사람들이 책임감있게 행동하고 존중하지 않는 강력한 이유가없는 한 (예 : 디버거, 코드 완성)이를 신뢰해야합니다.

만약 당신이 정말로 사적인 것을 가지고 있어야한다면, 확장으로 구현할 수 있습니다 (예 : CPython의 경우 C). 그러나 대부분의 경우 파이썬 작업 방식을 배우기 만하면됩니다.


답변

어떤 언어 (C ++의 포인터 산술, .NET / Java의 리플렉션)에서 멤버의 사생활을 피할 수없는 것은 아닙니다.

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

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


답변

class.__stuff명명 규칙은 프로그래머가 자신이 액세스하는 것은 아닙니다 알 수 있습니다 __stuff외부에서. 이름 맹 글링은 누군가가 우연히 그것을 할 것 같지 않습니다.

사실, 당신은 여전히이 문제를 해결할 수 있지만 다른 언어 (BTW도 가능하게 함)보다 훨씬 쉽지만 캡슐화에 관심이 있다면 Python 프로그래머는이 작업을 수행하지 않습니다.