나는 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
같은 규칙으로, _
접두사는 기술적으로 금지되지 않은 경우에도 멀리 떨어져 있음을 의미 합니다. 당신은 __foo
or 처럼 보이는 다른 클래스의 변수를 가지고 놀지 않습니다 _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 액세스 경로에도 사용할 수 있습니다.