source

왜 Python의 '프라이빗' 메서드는 실제로 비공개 방식이 아닐까요?

manysource 2022. 11. 23. 20:23

왜 Python의 '프라이빗' 메서드는 실제로 비공개 방식이 아닐까요?

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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

여기 모든 게 좋아 보여서 뭐라고 부를 수가 없어.그것은 사실 '사적'이다.음, 사실은 그렇지 않아요.입니다.dir()오브젝트상에서 Python이 모든 '프라이빗' 메서드를 위해 마법처럼 만든 새로운 메서드를 보여줍니다.

>>> 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 beginning
            matched = re.match( '^self\.', function_call)
            if not matched:
                print 'This is a private function. Go away.'
                return
        except:
            print 'This is a private function. Go away.'
            return

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

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

### End ###

내가 자바에서 파이썬으로 처음 왔을 때 는 이것이 싫었다.무서워서 죽을 뻔했어요.

오늘날 Python의 가장 마음에 드는 것은 이것뿐일지도 모릅니다.

저는 사람들이 서로를 믿고 코드 주위에 뚫을 수 없는 벽을 쌓을 필요가 없다고 느끼는 플랫폼에 있는 것을 좋아합니다.강하게 캡슐화된 언어에서는 API에 버그가 있고 무엇이 잘못되었는지 알아냈을 경우 필요한 메서드는 비공개이기 때문에 여전히 문제를 해결하지 못할 수 있습니다.Python의 태도는 "물론"입니다.만약 당신이 상황을 이해했다고 생각한다면, 아마도 당신은 그것을 읽었을지도 모른다, 우리가 말할 수 있는 것은 "행운을 빕니다!"뿐입니다.

기억하라, 캡슐화는 "보안"이나 아이들을 잔디밭에 들이지 못하게 하는 것과도 관련이 없다.이것은 코드 베이스를 이해하기 쉽게 하기 위해 사용해야 하는 또 다른 패턴일 뿐입니다.

Dive Into Python, 3.9에서 개인 기능:

엄밀히 말하면, 개인 방법은 클래스 밖에서 접근할 수 있지만 쉽게 접근할 수 없습니다.Python의 어떤 것도 진정으로 사적인 것은 없다.내부적으로는 개인 메서드나 속성의 이름이 순식간에 뒤섞여, 주어진 이름으로는 접근할 수 없는 것처럼 보인다.MP3FileInfo 클래스의 __parse 메서드는 _MP3FileInfo__parse라는 이름으로 액세스할 수 있습니다.이것이 흥미롭다는 것을 인정하고, 절대, 절대 실제 코드로 하지 않겠다고 약속하세요.개인 메서드는 개인적인 이유가 있지만 Python의 다른 많은 것들과 마찬가지로 결국 개인 메서드의 문제는 관습의 문제이지 강제성이 아닙니다.

일반적으로 사용되는 문구는 "우리는 모두 동의하는 어른이다"입니다.단일 언더스코어(노출하지 않음) 또는 이중 언더스코어(숨김)를 추가하는 것으로써, 클래스 유저에게 어떠한 방법으로든 멤버를 「프라이빗」하게 할 수 있습니다.단, 디버거나 코드 완성 등 특별한 이유가 없는 한 다른 모든 사람이 책임감 있게 행동하고 이를 존중할 것이라고 믿고 있습니다.

정말로 프라이빗한 것이 필요한 경우는, 확장으로 실장할 수 있습니다(예를 들면, CPython의 경우는 C).하지만 대부분의 경우, 당신은 단지 피토닉식으로 일을 하는 방법을 배울 뿐이다.

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

요점은 실수로 개인 메서드를 호출하려고 하면 오류가 발생한다는 것입니다.하지만 만약 당신이 당신의 발을 쏘고 싶다면, 그렇게 하세요.

당신은 OO 캡슐화로 당신의 물건을 보호하려고 하는 것은 아니지요?

중요사항:

의 .__name( 밑줄, 밑줄으로 (2개의 선행 밑줄, 1개의 후행 밑줄)로 _classname__name서, snowledge.classname는 선행 언더스코어가 제거된 현재 클래스 이름입니다.

therefore그 、__name직접 할 수 , 할 수 ._classname__name.

이는 변수 이름을 변경하여 쉽게 액세스할 수 있으므로 개인 데이터를 보호할 수 있다는 것을 의미하지 않습니다.

출처:

공식 문서의 "개인 변수" 섹션: https://docs.python.org/3/tutorial/classes.html#tut-private

class Cat:
    def __init__(self, name='unnamed'):
        self.name = name
    def __print_my_name(self):
        print(self.name)
        
        
tom = Cat()
tom.__print_my_name() #Error
tom._Cat__print_my_name() #Prints name

모듈 Atribute 이름이 단일 언더스코어(예를 들어 _foo)로 시작하는 경우에도 동일한 동작이 존재합니다.

"Atribut" "Import" "Import" 를 된 모듈 .from*★★★★★★★★★★★★★★★★:

from bar import *

단, 이는 규칙일 뿐 언어의 제약이 아닙니다.이러한 속성은 개인 속성이 아니며 모든 임포터가 참조하고 조작할 수 있습니다.이 때문에 파이썬은 진정한 캡슐화를 구현할 수 없다는 주장도 있다.

언어 디자인 선택지 중 하나일 뿐입니다.어느 정도 그들은 정당하다.그들은 당신이 방법을 부르기 위해 꽤 멀리까지 가야 할 필요가 있도록 만들어요. 만약 당신이 그것을 정말로 필요로 한다면, 당신은 분명히 꽤 그럴만한 이유가 있을 거예요!

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

프라이빗 메서드 및 Atribute의 가장 중요한 우려사항은 개발자에게 클래스 밖에서 호출하지 말라고 하는 것입니다.이것은 캡슐화입니다.보안과 캡슐화를 혼동할 수 있습니다.다음에 나타낸 것과 같은 구문을 의도적으로 사용하는 경우 캡슐화를 원하지 않습니다.

obj._MyClass__myPrivateMethod()

저는 C#에서 이직했는데 처음에는 저도 이상했지만 얼마 지나지 않아 OOP에 대한 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'

9.6부터. 개인 변수:

머글링 규칙은 대부분 사고를 방지하기 위해 설계되어 있습니다.또, 프라이빗하다고 생각되는 변수에 액세스 하거나 변경할 수도 있습니다.이것은 디버거와 같은 특수한 상황에서도 유용할 수 있습니다.

왜 Python의 '프라이빗' 메서드는 실제로 비공개 방식이 아닐까요?

내가 알기론, 그들은 사적일 수 없어.사생활은 어떻게 집행될 수 있을까요?

은 ' 회원은 이 안 된다' 입니다 " " " " " " "self 먹히네.selfPython ★★★★★★★★★★★★★★★★★★★★★★★★★★.이는 함수의 첫 번째 파라미터에 대해 일반적으로 사용되는 이름에 지나지 않습니다.

언급URL : https://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private