수업당이 아닌 인스턴스 수준에서 정의 된 속성 사용
-
06-07-2019 - |
문제
내가 달성하려는 것은 다음과 같습니다.
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