[python] 파이썬에는 클래스에 “비공개”변수가 있습니까?

나는 Java 세계에서 왔으며 Bruce Eckels의 Python 3 Patterns, Recipes and Idioms를 읽고 있습니다.

클래스에 대해 읽는 동안 파이썬에서는 인스턴스 변수를 선언 할 필요가 없다고 말합니다. 당신은 생성자에서 그것들을 사용하고 붐이 있습니다.

예를 들어 :

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

그것이 사실이라면 클래스의 모든 객체는 클래스 외부의 Simple변수 값을 변경할 수 있습니다 s.

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

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

Java에서는 공개 / 개인 / 보호 변수에 대해 배웠습니다. 이러한 키워드는 클래스 외부의 어느 누구도 액세스 할 수없는 클래스의 변수를 원하기 때문에 의미가 있습니다.

왜 파이썬에서는 이것이 필요하지 않습니까?



답변

문화적입니다. 파이썬에서는 다른 클래스의 인스턴스 나 클래스 변수에 쓰지 않습니다. Java에서 실제로 원하는 경우 동일한 작업을 수행하는 데 방해가되는 것은 없습니다. 결국 동일한 클래스 효과를 얻기 위해 클래스 자체의 소스를 편집 할 수 있습니다. 파이썬은 보안을 강조하고 프로그래머가 책임을 지도록 장려합니다. 실제로 이것은 매우 훌륭하게 작동합니다.

어떤 이유로 개인 변수를 에뮬레이트하려는 경우 항상 PEP 8__접두사를 사용할 수 있습니다 . 파이썬은 변수의 이름처럼 엉망으로 그들은 당신이 있지만 (이를 포함하는 클래스 외부의 코드에 쉽게 볼 수없는 걸 그렇게 할 수 있습니다 당신은 그냥 같이있는 거 결정 충분히 당신이 경우 주위에 얻을 수있는 당신이 그것을 작동하는 경우 자바의 보호를 돌아 다니기 ).__foo

같은 규칙으로, _접두사는 기술적으로 금지되지 않은 경우에도 멀리 떨어져 있음을 의미 합니다. 당신은 __fooor 처럼 보이는 다른 클래스의 변수를 가지고 놀지 않습니다 _bar.


답변

파이썬의 개인 변수는 다소 해킹입니다. 인터프리터는 의도적으로 변수 이름을 바꿉니다.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

이제 __var클래스 정의 외부에서 액세스하려고 하면 실패합니다.

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123

그러나 다음과 같이 쉽게 벗어날 수 있습니다.

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456

당신은 아마 OOP의 방법을 다음과 같이 호출되는 것을 알고 x.printVar() => A.printVar(x), 경우 A.printVar()에 일부 필드에 액세스 할 수 있습니다 x,이 필드는 액세스 할 수 밖에 A.printVar() … 결국, 함수는 재사용을 위해 만들어, 내부의 문에 주어진 특별한 능력이 없다.

컴파일러가 관련된 경우 게임이 다릅니다 ( 개인 정보 보호는 컴파일러 레벨 개념입니다 ). 액세스 제어 수정자를 사용하여 클래스 정의에 대해 알고 있으므로 컴파일 타임에 규칙을 따르지 않으면 오류가 발생할 수 있습니다.


답변

위의 많은 의견에서 올바르게 언급했듯이 Access Modifiers의 주요 목표를 잊지 마십시오. 당신은 개인 필드를 볼 때 당신은 그것을 엉망으로하지 않습니다. 그래서 그것은 주로 구문 설탕으로 파이썬에서 _와 __에 의해 쉽게 달성됩니다.


답변

밑줄 규칙에 개인 변수의 변형이 있습니다.

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

약간의 미묘한 차이가 있지만 프로그래밍 패턴 이데올로기 적 순도를 위해 충분합니다.

@private 데코레이터에는 개념을 더 밀접하게 구현하지만 YMMV를 구현하는 예가 있습니다. 아마도 메타를 사용하는 클래스 정의를 작성할 수도 있습니다.


답변

“자바에서는 공개 / 개인 / 보호 변수에 대해 배웠다”

“파이썬에서는 왜 이것이 필요하지 않습니까?”

같은 이유로 Java 에서는 필요 하지 않습니다 .

당신은 무료로 사용할 수있어 – 사용 여부 privateprotected.

파이썬과 자바 프로그래머로서, 나는 것으로 나타났습니다 privateprotected매우 중요한 설계 개념이다. 그러나 실제적인 문제로서, 수십 자바와 파이썬의 라인의 수천에, 나는 결코 실제로 사용되지 privateprotected.

왜 안돼?

내 질문은 “누구에게서 보호 되었습니까?”입니다.

우리 팀의 다른 프로그래머? 그들은 소스를 가지고 있습니다. 보호 할 수있는 것은 무엇을 의미합니까?

다른 팀의 다른 프로그래머? 그들은 같은 회사에서 일합니다. 그들은 전화로 소스를 얻을 수 있습니다.

고객? 일반적으로 고용 작업 프로그래밍입니다. 클라이언트는 일반적으로 코드를 소유합니다.

그렇다면 누구로부터 정확히 보호하고 있습니까?


답변

앞에서 언급했듯이 변수 나 메소드 앞에 밑줄을 붙여서 변수 나 메소드가 개인용임을 표시 할 수 있습니다. 이것으로 충분하지 않다면 언제든지 property데코레이터를 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

이런 식으로 누군가 또는 참조하는 bar것은 실제로 bar변수 자체가 아닌 함수 의 반환 값을 참조 하므로 액세스 할 수는 있지만 변경할 수는 없습니다. 그러나 누군가가 정말로 원한다면, 단순히 _bar새로운 가치를 사용 하고 할당 할 수 있습니다. 반복해서 말한 것처럼 누군가가 숨기고 싶은 변수와 메소드에 액세스하지 못하게하는 확실한 방법은 없습니다. 그러나 property변수를 편집하지 않도록 보낼 수있는 가장 명확한 메시지는 사용 하는 것입니다. https://docs.python.org/3/library/functions.html#property에property 설명 된대로 더 복잡한 getter / setter / deleter 액세스 경로에도 사용할 수 있습니다.


답변

파이썬은 클래스 이름을 두 개의 밑줄로 시작하는 식별자 앞에 자동으로 추가하는 기능을 통해 개인 식별자를 제한적으로 지원합니다. 이것은 프로그래머에게 투명하지만 대부분의 경우 이러한 방식으로 명명 된 변수는 전용 변수로 사용할 수 있습니다.

자세한 내용은 여기 를 참조 하십시오 .

일반적으로 파이썬의 객체 방향 구현은 다른 언어에 비해 약간 원시적입니다. 그러나 나는 이것을 실제로 즐긴다. 매우 개념적으로 간단한 구현이며 동적 언어 스타일에 잘 맞습니다.