2016-11-03 1 views
2

이 프로젝트는 다양한 소스의 여러 개체와 감사 및 데이터 소스 간의 충돌을 해결하기 위해 개체에 대한 많은 정보를 수집합니다 각 속성에 대한 많은 메타 데이터를 유지해야합니다.Python : 클래스의 변수에 속성을 추가하고 할당 (서술자 클래스)에서 살아남도록

age = 21 
age_metadata = { 
    'source' : 'office gossip', 
    'relability' : 0 
    { 

문제는 클래스가 이렇게 보이기 시작합니다. 추한 외모와 속성의 모든의 수는 내가 원하는 그래서이 두 배로

class Person 
    def __init__(self, id,): 
     self.id = id 
     self.id_meta = None 
     self.age = None 
     self.age_meta = None 
     self.name = None 

는 둥지에 각 속성에서 메타 데이터입니다. 그래서 내가 필요한 경우 bob.age_meta 대신 bob.age.meta을 호출 할 수 있으며 속성을 다소 변경하지 않고 남겨두기를 원합니다. 그래서 나는 항상 내가 그것을 좋아 사용하는 것을 원하는 :

def main(): 
    bob = Person(1) 
    bob.age.meta = 'random metadata' 
    bob.age = 30 
    assert bob.age.meta == 'random metadata' 

이 지금은이 메타 데이터를 보존하기 위해 마법을 metaclassing/할당 + 약간의 원숭이가 패치를 차단하기 위해 기술자 클래스의 콤보를 사용하여 가능해야한다고 생각을 .. 그러나 나는이 모든 기능에 익숙하지 않고 매우 길을 잃고 있습니다. 여기에 내 현재 스케치가 있습니다. 작업 코드에서 길게 :

class AttributeWithMeta(object): 
    """interceot attribute fucntions""" 

    def __get__(self, instance, owner): 
     return self._value 

    def __set__(self, instance, value): 
     """take attribute and somehow replace it with monkey patched version""" 
     self._value = magic(value,meta) 

    @staticmethod 
    def magic(value, meta): 
     """adds meta attribute to objects regardless of type""" 
     return value_with_meta 


class Person(object): 
    age = AttributeWithMeta() 

    def __init__(self, id): 
     self.id = id 

올바른 방향으로 가고 있습니까? 내가 할 수있는 다른 방법이 있습니까? 나는 여기서 불가능한 일을하려고 노력하고 있는가?

P.S 최악의 경우 age.get_meta()은 속성에 문제가있는 경우 허용됩니다. 당신의 Person 클래스는 여기에 문제에 발언권을 얻을 수 없습니다 있도록

+0

다른 방법으로는 데이터베이스에서 모델링하는 것이 좋습니다.예를 들어 sqlalchemy + sqlite를 할 수 있습니다. – tdelaney

답변

1
bob.age.meta 
^^
    | |_______ This lookup can be managed by type(bob.age) class 
    | 
    |___________ This lookup can be managed by type(bob) class, i.e. Person 

.meta의 속성 액세스는 bob.age 객체에 의해 완전히 처리됩니다.

Person 클래스에 디스크립터를 정의하여 age 속성의 설정/가져 오기/삭제가 Person 인스턴스에서 어떻게 작동하는지 제어 할 수 있습니다. 사용자 인스턴스와 속성 사이에 own the dot을 입력하면 원하는 모든 작업을 수행 할 수 있습니다. 하지만 그 힘은 두 번째 점까지 도달하지 못합니다. 즉, .agemeta 사이입니다.

bob.age이 문자 그대로 정수 30을 반환하게하려면 bob.age.meta을 얻는 데 어려움을 겪겠지만 AttributeError을 발생 시키십시오. int 클래스에 정의 된 설명자를 필요로하고, 파이썬에서 원숭이 패치 내장 유형을 사용할 수 없기 때문입니다. 어쨌든 terrible and unreliable hacks 없이는 없습니다.

bob.age이 개체의 컨테이너 종류와 관련 메타 데이터를 반환하는 것이 좋은 경우 Person 클래스의 설명자를 사용하여 원하는 것이 가능합니다. 하지만 bob.age이 객체 만 반환하고 bob.age.meta을 반환하여 메타 데이터 만 반환하려는 경우 잘못된 트리를 짖는 것 같아요. 각 Person 인스턴스가 직접 meta DICT을 가지고 당신이 밥의 age 속성에 관한 메타 데이터 예를 bob.meta['age']에 대해 찾아 볼 수 있도록

훨씬 덜 복잡 설계는 것입니다.

+0

나는 옳은 길에 있다고 생각합니다. 나이가 더 이상 타입이 아니라면 괜찮습니다. 대신에'__set__'과 .__meta__를 제외한 모든 메소드를 방어하는 컨테이너 인 ._value 속성은 그것을 수호한다 ._ 메타 – Nath

관련 문제