2013-01-14 2 views
2

어떤 인스턴스 클래스의 클래스를 생성하는 가장 편리한 방법은 이 될 수 없으므로 클래스 외부에서이 변경되었습니다 (여전히 값을 얻을 수 있음). 클래스의 메서드 안에 self.var = v을 호출 할 수는 있지만 ClassObject().var = v은 클래스 외부에 있지 않습니다.인스턴스 '애트리뷰트를 편집 할 수없는 파이썬 클래스

나는 __setattr__()을 사용하는 것을 시도했지만,이를 무시한 경우 name 속성을 __init__() 메소드에서 시작할 수 없습니다.

class MyClass(object): 
    def __init__(self, name): 
     object.__setattr__(self, "name", name) 
    def my_method(self): 
     object.__setattr__(self, "name", self.name + "+") 
    def __setattr__(self, attr, value): 
     raise Exception("Usage restricted") 

지금이 솔루션이 작동하고, 그것은 충분하지만, 심지어 더 나은 솔루션이 있는지 궁금 해서요 : 유일한 방법 내가 지금 뭐하는 거지하는 __setattr__()을 무시하고 object.__setattr__()을 사용하는 것입니다. 이 문제는 다음과 같습니다. object.__setattr__(MyClass("foo"), "name", "foo_name")은 수업 외부의 어느 곳에서도 계속 호출 할 수 있습니다.

변수를 클래스 외부에서 설정하는 것을 완전히 막을 수있는 방법이 있습니까?

편집 : 제가 여기 property 찾는 게 아니에요 언급하지 바보, 당신의 일부는 이미 변경 self._name을 떠날 것이기 때문에, 그러나 그것은 나를 위해 충분하지 않습니다, 그것을 대답했다.

+3

아니, 없다. 어쨌든 순수한 파이썬에서는 아닙니다. 왜 이것을 필요로합니까? –

+1

불가능하지만, 왜 그런 식으로해야 하는지를 묻는 것은 가치가 있습니다. – mgilson

+0

아마도 읽기 전용 속성이 필요합니다. 예를 들어'STEAM_ID'가 좋을 것입니다. –

답변

3

아니, 당신은 순수 파이썬에서이 작업을 수행 할 수 없습니다.

속성을 사용하여 속성을 읽기 전용으로 표시 할 수 있습니다. - 접두어로 밑줄을 사용하여 '개인'은 대신 속성 :

class Foo(object): 
    def __init__(self, value): 
     self._spam = value 

    @property 
    def spam(self): 
     return self._spam 

은 위의 코드 만 속성에 대한 게터를 지정합니다 파이썬은 지금 Foo().spam에 대한 값을 설정할 수 없습니다 : 물론

>>> class Foo(object): 
...  def __init__(self, value): 
...   self._spam = value 
...  @property 
...  def spam(self): 
...   return self._spam 
... 
>>> f = Foo('eggs') 
>>> f.spam 
'eggs' 
>>> f.spam = 'ham' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: can't set attribute 

, 당신은 여전히 ​​외부에서 '개인'_spam 속성에 액세스 할 수 있습니다

>>> f._spam 
'eggs' 
>>> f._spam = 'ham' 
>>> f.spam 
'ham' 

당신은 이중 밑줄 규칙을 사용할 수 있습니다, 여기서 시작 부분에있는 __의 속성 이름은 컴파일시 이름이 바뀝니다. 이것은 외부에서 접근 할 수없는 속성을 만드는 것을 의미하지는 않습니다. 대신 속성이 서브 클래스에 의해 덮어 쓰지 않도록 보호하는 것이 목적입니다.

class Foo(object): 
    def __init__(self, value): 
     self.__spam = value 

    @property 
    def spam(self): 
     return self.__spam 

당신은 여전히 ​​이러한 속성에 액세스 할 수 있습니다

>>> f = Foo('eggs') 
>>> f.spam 
'eggs' 
>>> f.__spam 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'Foo' object has no attribute '__spam' 
>>> f._Foo__spam 
'eggs' 
>>> f._Foo__spam = 'ham' 
>>> f.spam 
'ham' 
+0

'property'를 찾지는 못했지만 다른 사람이'property'를 찾고 있을지도 모른다고 대답했기 때문에 답을 받아 들일뿐입니다. –

2

파이썬에서 캡슐화를 수행하는 엄격한 방법은 없습니다. 당신이 할 수있는 최선의 방법은 개인 속성으로 의도 된 2 개의 밑줄 __을 붙이는 것입니다. 이로 인해 클래스 이름 (_ ClassName _AttribName)으로 변경 될 수 있으므로 상속 된 클래스에서이 클래스를 사용하려고하면 기본 멤버가 참조되지 않습니다. 그래도 getattrib() 또는 setattrib()을 사용하면 이름이 엉망이되지 않습니다.

__dir()__을 숨기려면이를 다시 정의 할 수도 있습니다.

+1

답장을 보내 주셔서 감사합니다.이 질문을 받아 들일 수 있었고 upvote를 주셨습니다. –

2

이러한 동작을 시뮬레이션하기 위해 속성을 사용할 수 있지만 Martijn이 말했듯이 변수에 직접 액세스 할 수 있습니다. 이렇게하는 것은 파이썬 철학을 이해하지 못한다는 신호입니다. 이것을 확인하십시오.

Why Python is not full object-oriented?

속성 방법 :

http://docs.python.org/2/library/functions.html#property

class C(object): 
    def __init__(self): 
     self._x = None 

    def getx(self): 
     return self._x 
    def setx(self, value): 
     raise Exception("Usage restricted") 
    x = property(getx, setx) 
+0

이것은 OP가 요구 한 것을 수행하지 않습니다. –

+0

실제로 OP가 원하는 것은 python에서는 불가능합니다. 적어도 zen을 따르지는 않습니다. –

+0

예, 알고 있습니다. 대답이 제시되는 방식은 그것이 가능한 것처럼 보이게합니다. 그래서 제가 다운 투표했습니다. 당신이 대답에 '불가능'지점을 만들면 투표를 취소 할 것입니다. –

관련 문제