문제

내가 달성하려는 것은 다음과 같습니다.

class object:
    def __init__(self):
        WidthVariable(self)

        print self.width
        #Imagine I did this 60frames/1second later
        print self.width

#output:
>>0
>>25

내가하고 싶은 일 (위와 같이) : 언제 WidthVariable - 클래스 - 생성되면 변수를 추가합니다. width 대상에 사례. 이 변수는 정상적인 속성처럼 작용하지만이 경우에는 읽기 전용입니다 ( fget 변수가 설정됩니다). 또한, fget 정의 된 함수를 호출합니다 WidthVariable 무엇을 결정합니다 width 돌려 주다.

그러나, 나는 이것을 어떻게 해야할지 전혀 모른다! 일반 속성을 사용하여 시도했지만 인스턴스 당 클래스에서만 작동한다는 것을 알았습니다. 사용하는 코드는 위의 것과 최대한 비슷해야합니다 (즉, __init__WidthVariable 설정해야합니다 width 변수, 다른 곳). 또한, self.width 내가 부르는 것이 무엇인지하지 않기 때문에 기능 할 수 없습니다. self.width(), 원해요 self.width (내가 가진 나머지 디자인과 함께 유지되기 때문입니다).

명확히하기 위해, 완전한 코드는 다음과 같습니다.

class MyObject:
    def __init__(self)
        WidthVariable(self)
        print self.width

class WidthVariable:
    def __init__(self, object)
        object.width = property(self.get_width)

    def get_width(self):
        value = #do_stuff
        return value #The Value

#output:
>>25 #Whatever the Value was
도움이 되었습니까?

해결책

@jonathan이 말했듯이 설명자 (속성 포함)는 인스턴스 당이 아닌 클래스 당이기 때문에 각 인스턴스가 자체 클래스를 개별화하도록하는 것입니다. Metaprogramming이 진행되는 한 그것은 꽤 얕고 쉽습니다.-) ... :

class Individualistic(object_or_whatever_bases):
  def __init__(self, whatever_args):
    self.__class__ = type('GottaBeMe', (self.__class__, object), {})
    # keep rocking...!-)

나도 추가하고 있습니다 object (파이썬에서) 필요하기 때문에 명시 적으로 2.*, 그리고 당신은 그것이 당신이 사용하고있는 것이라고 말합니다 !!!) 수업을 새로운 유형으로 만들었습니다. 레거시 클래스를 더 이상 사용하지 말고, 속성과 관련하여 올바르게 행동하지 않습니다. 더 이상 물체에서 명시 적으로 상속 해야하는 요구 사항!).

이제 배치 된 모든 설명 자 self.__class__.__dict__ 이 사례에만 영향을 미치지 않습니다. 약간의 오버 헤드가 있습니다 (각각 GottaBeMe 클래스와 각 인스턴스에는 고유 한 인스턴스가 있습니다 __dict__, 등), 그러나 너무 끔찍한 것은 없습니다.

이제 원래 요청을 충족시키는 데 필요한 것은 다음과 같습니다.

class WidthVariable:
    def __init__(self, object)
        object.width = property(self.get_width)

(또한 이름을 바꿉니다 object Arg는 내장 된 내장에 짓밟히는 것을 피하고 항상 모든 클래스를 새 스타일로 만들어야하기 때문에 새로운 스타일을 만들기 위해 : :) :

class WidthVariable(object):
    def __init__(self, obj)
        obj.__class__.width = property(self.get_width)

당신이 볼 수 있듯이 너무 검은 마그니는 아무것도 없습니다!-)

다른 팁

나는 당신이 당신의 모범을 구축 한 방식을 이해하지 못하고, "정상적인 속성"에 대한 의미를 이해하지 못합니다. 수업에서만 작동 "합니다. 읽기 전용 속성을 만드는 방법은 다음과 같습니다.

class Foo(object):
    # create read-only property "rop"
    rop = property(lambda self: self._x)

    def __init__(self):
        self._x = 0

    def tick(self):
        self._x += 1    

f = Foo()
print f.rop # prints 0
f.tick()
f.tick()
print f.rop # prints 2
f.rop = 4 # this will raise AtributeError

나는 지금 당신의 질문을 이해하고 있다고 믿고, 나는 또한 당신이 운없는.

새 스타일 클래스의 경우 특수 메소드의 암시 적 호출은 객체의 인스턴스 사전이 아닌 오브젝트 유형에 정의 된 경우에만 올바르게 작동합니다.

디스크립터 (속성을 구현하는 데 사용되는)는 클래스 __dict__, 그리고 그 안에는 나타날 수 없습니다 인스턴스 __dict__. 다시 말해, 파이썬은 루비가 아닙니다!

나는 경건한 Python Metaprogrammer에서 행복하게 교정을 기다리고 있지만, 내가 옳다고 생각합니다.

당신이 원하는 것을 명확하지 않습니까? 그러나 나는 당신이 각 인스턴스에 대해 obj.width가 사용자 정의되기를 원한다고 가정합니다. 여기서는 일반 속성을 사용하여 쉬운 방법이 있습니다. 너비 속성은 인스턴스 당 콜백에 의해 반환 된 값을 반환합니다.

class MyClass(object):
    def __init__(self, callback):
        self.callback = callback

    def get_width(self):
        return self.callback()

    width = property(get_width)

def w1(): return 0
def w2(): return 25

o1 = MyClass(w1)
o2 = MyClass(w2)

print o1.width
print o2.width

콜백을 전달할 수없는 경우 ridthvariable에 할당 할 수 있으며 예를 들어 너비를 반환합니다.

class MyClass(object):
    def __init__(self):
        self.callback = WidthVariable(self)

    def get_width(self):
        return self.callback()

    width = property(get_width)

class WidthVariable(object):
    def __init__(self, obj):
        self.obj = obj

    def __call__(self):
        return hash(self.obj)

o1 = MyClass()
o2 = MyClass()

print o1.width
print o2.width
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top