2013-04-26 1 views
11

Python의 장식 시스템. aClassObect.attribute에 전화 할 때 사용자 지정 코드를 실행할 수 있다는 점이 좋습니다. 특히 속성을 설정할 때 데이터의 유효성 검사에 사용됩니다. 그러나 내가 원하지만, 찾을 수없는 한 가지는 존재하지 않는 특성을 설정할 때 사용자 지정 코드를 실행하는 방법입니다. 예를 들어, 나는 다음 클래스있어 말 : 나는 클래스 C의 인스턴스 인, myObj이있는 경우, 이제클래스에서 정의되지 않은/구현되지 않은 속성에 대한 파이썬 "모든 방법을 잡으십시오"

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

    @property 
    def x(self): 
     """I'm the 'x' property.""" 
     return self._x 

    @x.setter 
    def x(self, value): 
     self._x = value 

    @x.deleter 
    def x(self): 
     del self._x 

을, 나는 myObject.x = 42 전화, 그것을 위해 중대하다 적절한 세터를 실행합니다 데이터의 유효성 검사. 그러나 이로 인해 누군가가 myOjbect.b = 47에 전화하는 것을 멈추지 않으며 행복하게 b이라는 새 속성을 만듭니다. 새로운 속성을 설정할 때 특별한 코드를 실행할 수있는 방법이 있습니까? 나는 "오류,이 속성은 존재하지 않는다"와 같은 말을하기 위해 오류를 제기 할 수있는 능력을 가지고있었습니다.

+2

데이터베이스에 API로 사용되는 클래스가 있습니다. 각 인스턴스는 항목을 나타냅니다. 데이터베이스의 필드를 나타내는 객체의 속성을 수정 한 후에는'object.save()'를 호출하여 DB를 업데이트합니다. 오히려 DB에 실제로 존재하지 않기 때문에 필드가 자동으로 삭제되기보다는 오히려 오류가 발생합니다. –

답변

9

Elazar 님의 답변을 좀 더 상세하게 설명하려면 __setattr__ 마법 방법을 덮어 쓰고 속성이 이미 존재하는지 확인하십시오. 그렇지 않은 경우 예외를 발생시킵니다. 그것은 당신이 존재하지 않는 속성에 대한 요청을 처리하려면 __getattr__ 또는 __getattribute__을 무시할 수도 있습니다

def __setattr__(self, name, value): 
    if not hasattr(self, name): # would this create a new attribute? 
     raise AttributeError("Creating new attributes is not allowed!") 
    super(C, self).__setattr__(name, value) 

하지만, 특정 문제에 대한이 아마하지 설명했다 : 여기에 당신의 클래스처럼 볼 수 있었다 무엇 필요한.

위의 그림에서 __setattr__은 deleter로 인해 현재 속성에서 완전히 재생되지 않습니다. myObj.x을 삭제하면 나중에 x에 액세스하려고하면 getter가 예외를 발생시킵니다. 즉, 은 x이 기존 속성인지 확인하면 False을 반환하므로 내 __getattr__에서 다시 만들 수 없습니다. 특정 애트리뷰트를 정말로 삭제하고 재 작성할 수 있어야한다면 더 복잡한 __setattr__ 구현이 필요하다. (단지 hasattr에 의존하는 것이 아니라 원하는 이름을 가진 프로퍼티를 클래스에서 체크 할 수있다.)

+0

오 기다려, 나는 이것이 잘 될 것이라고 확신했지만, 잡다한 것이있다.이 제한은 값을 초기화 할 때 생성자를 포함하여 어디에서나 적용된다. 방금 해봤고, 생성자의'AttributeError'를 가지고 멈추었습니다. 이 문제를 해결할 방법이 있습니까? –

+0

@ J-bob : 아, 네. 'super (C, self) .__ setattr __ ("_ x", None)'과 같은 것을 명시 적으로 호출해야한다. 체크를 우회하려면 속성을 설정한다. – Blckknght

+0

좋은 해결책을 찾았습니다. 내 파일 상단에, 나는'수입 검사 '를한다. 'hasattr (self, name) :'과'insattr (self, name) '그리고 inspect.stack() [1] [3]! ='__init __ ':'를 사용하여 라인을 대체합니다. 'inspect.stack'은 호출 스택을 조사해 보겠습니다. 그래서이 코드는 호출 스택의 이름을 검사합니다. 호출하는 메소드가'__init__'이라면 속성을 생성 할 수 있습니다. 그렇지 않으면 오류가 발생합니다. 이를 보여주기 위해 답을 수정하는 것이 좋습니다. –

9

__getattr____setattr__을 재정의하십시오.

관련 문제