나는 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변수 값을 변경할 수 있습니다
예를 들면 다음과 같습니다.
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 에서는 필요 하지 않습니다 .
당신은 무료로 사용할 수있어 – 사용 여부 private와 protected.
파이썬과 자바 프로그래머로서, 나는 것으로 나타났습니다 private과 protected매우 중요한 설계 개념이다. 그러나 실제적인 문제로서, 수십 자바와 파이썬의 라인의 수천에, 나는 결코 실제로 사용되지 private나 protected.
왜 안돼?
내 질문은 “누구에게서 보호 되었습니까?”입니다.
우리 팀의 다른 프로그래머? 그들은 소스를 가지고 있습니다. 보호 할 수있는 것은 무엇을 의미합니까?
다른 팀의 다른 프로그래머? 그들은 같은 회사에서 일합니다. 그들은 전화로 소스를 얻을 수 있습니다.
고객? 일반적으로 고용 작업 프로그래밍입니다. 클라이언트는 일반적으로 코드를 소유합니다.
그렇다면 누구로부터 정확히 보호하고 있습니까?
답변
앞에서 언급했듯이 변수 나 메소드 앞에 밑줄을 붙여서 변수 나 메소드가 개인용임을 표시 할 수 있습니다. 이것으로 충분하지 않다면 언제든지 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 액세스 경로에도 사용할 수 있습니다.