it-swarm-ko.tech

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

파이썬은 다음과 같이 이름에 두 개의 밑줄을 붙임으로써 클래스 내에서 'private'메소드와 변수를 생성 할 수있는 기능을 제공합니다 : __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()

내가 한 것은 public 메서드와 private 메서드를 사용하여 클래스를 만들고 인스턴스화하는 것입니다.

다음으로, 나는 public 메소드를 호출한다.

>>> obj.myPublicMethod()
public method

그런 다음 개인적인 방법을 시도하고 호출합니다.

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

모든 것이 여기 좋아 보인다. 우리는 그것을 부를 수 없습니다. 그것은 사실, '사적'입니다. 음, 실제로 그렇지 않습니다. dir () 을 실행하면 python이 모든 '비공개'메소드에 대해 마술처럼 생성하는 새로운 마법 방법이 나타납니다.

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

이 새로운 메소드의 이름은 항상 밑줄이고 클래스 이름 다음에 메소드 이름이옵니다.

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

캡슐화에 너무 많은, 어?

어쨌든 필자는 항상 파이썬이 캡슐화를 지원하지 않는다고 들었습니다. 그렇다면 왜 시도해 보시겠습니까? 뭐라 구요?

596
willurd

이름 스크램블은 서브 클래스가 자신의 수퍼 클래스의 개인 메소드와 속성을 우연히 덮어 쓰지 않도록하기 위해 사용됩니다. 외부에서 의도적으로 액세스하지 못하도록 설계되지 않았습니다.

예 :

>>> 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}

물론, 두 개의 다른 클래스가 같은 이름을 가진다면 그것은 분해됩니다.

548
Alya

개인 기능의 예

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 ###
205
arun

내가 처음 자바에서 파이썬으로 왔을 때 증오. 그것은 나를 죽음으로 두려워했다.

오늘날 파이썬에 관한 한 가지 가장 좋아합니다 일 수도 있습니다.

나는 사람들이 서로를 신뢰하고 코드 주위에 뚫을 수없는 벽을 만들 필요가 없다고 생각하는 플랫폼에있는 것을 좋아합니다. 강력하게 캡슐화 된 언어에서 API에 버그가 있고 잘못 된 것이 무엇인지 파악한 경우 필요한 메서드가 비공개이므로 문제를 해결할 수 없습니다. 파이썬에서 태도는 "확실하다"이다. 당신이 상황을 이해한다고 생각한다면, 아마도 당신은 그것을 읽었을 것입니다, 그러면 우리가 말할 수있는 것은 "행운"입니다.

캡슐화는 "보안"과 약한 관계가 아니며 아이들을 잔디에서 보호하지도 않습니다. 이는 코드 기반을 이해하기 쉽게 만드는 또 다른 패턴입니다.

146
Thomas Ahle

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

엄밀히 말하면, 사적인 방법은 수업 외부에서 쉽게 접근 할 수 있습니다. 파이썬의 어떤 것도 진정으로 사적입니다. 내부적으로, 개인 메소드와 속성의 이름은 주어진 이름으로 액세스 할 수없는 것처럼 보이도록 즉시 엉망이되고 엉망이됩니다. _MP3FileInfo__parse라는 이름으로 MP3FileInfo 클래스의 __parse 메서드에 액세스 할 수 있습니다. 이것이 흥미 롭다는 것을 인정하고, 결코 실제 코드로 그렇게하지 않겠다고 약속하십시오. 개인용 메서드는 이유가 있기 때문에 비공식적이지만 파이썬의 다른 많은 것들과 마찬가지로 궁극적으로 자신의 기밀성은 강제가 아니라 관습의 문제입니다.

139
xsl

일반적으로 사용되는 문구는 "우리 모두는 여기 성인을 동의하고 있습니다"입니다. 단일 밑줄을 붙이거나 (노출시키지 않음) 또는 밑줄을 두 번 숨기 (숨기기)하여 클래스의 사용자에게 회원에게 어떤 방식 으로든 '비공개'가되도록합니다. 그러나 다른 모든 사람들이 책임감있게 행동하고 존중하지 않도록해야합니다 (디버거, 코드 완성 등).

비공개로 설정해야하는 항목이 있다면 확장 프로그램 (CPython의 경우 C)에서 구현할 수 있습니다. 그러나 대부분의 경우 일을하는 Pythonic 방식을 배우기 만하면됩니다.

87
Tony Meyer

어떤 언어 (C++의 포인터 연산, .NET/Java의 Reflections)에서 멤버의 privateness를 절대적으로 해결할 수있는 것은 아닙니다.

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

편집 : 당신은 OO 캡슐화하여 물건을 확보하려고하지 않아?

32
Maximilian

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

from* 메소드를 사용할 때 그와 같은 모듈 속성은 가져 오기 모듈에 복사되지 않습니다 (예 :

from bar import *

그러나 이는 언어 관례가 아닌 관습입니다. 이것들은 private 속성이 아닙니다. 모든 수입업자가 참조하고 조작 할 수 있습니다. 이 때문에 파이썬은 진정한 캡슐화를 구현할 수 없다고 주장합니다.

12
Ross

class.__stuff 명명 규칙을 사용하면 프로그래머는 외부에서 __stuff에 액세스 할 의도가 없다는 것을 알 수 있습니다. 이름이 맹 글링되면 누구나 우연히 그렇게 할 것 같지 않습니다.

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

12
Nickolay

그것은 그 언어 디자인 선택 중 하나 일뿐입니다. 어느 정도 그들은 정당화된다. 그들은 당신이 방법을 시도하고 호출하기 위해 당신의 방식에서 꽤 멀어 질 필요가 있도록합니다. 그리고 당신이 그것을 정말로 필요로한다면, 당신은 꽤 좋은 이유가 있어야합니다!

디버깅 후크 및 테스트는 가능한 응용 프로그램으로 떠오르고 물론 책임감있게 사용됩니다.

12
ctcherry

파이썬 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

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

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

4
Alberto

Private 메소드와 속성에 대한 가장 중요한 관심사는 클래스 외부에서 호출하지 말 것을 개발자에게 알려주는 것이며 이것은 캡슐화입니다. 캡슐화로 인한 보안 오해가있을 수 있습니다. 하나가 고의적으로 당신이 언급 한 (벨로우즈) 문법을 사용하면 캡슐화를 원하지 않습니다.

obj._MyClass__myPrivateMethod()

나는 C #에서 마이 그 레이션했고, 처음에는 이상하게 보였지만, 잠시 후 파이썬 코드 디자이너가 OOP에 대해 생각하는 방식 만 다르다는 생각에 왔습니다.

2
Afshin Amiri

왜 파이썬의 '비공개'메소드가 실제로 비공개가 아닌가?

내가 알기로, 그들은 () 개인적 일 수 없습니다. 프라이버시는 어떻게 시행 될 수 있습니까?

분명한 대답은 "비공개 멤버는 self을 통해서만 액세스 할 수 있음"이지만 작동하지 않습니다. self은 Python에서는 특별하지 않습니다. 함수의 매개 변수.

1
user200783