باستخدام خصائص محددة على سبيل المثال مستوى لا في الدرجة
-
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
المحلول
وبما @جوناثان يقول واصفات (بما في ذلك العقارات) هي في الدرجة وليس في-سبيل المثال ، فإن الطريقة الوحيدة للحصول على مختلف في الدرجة واصفات هو أن يكون كل مثيل تفريد فئتها الخاصة.هذا هو سطحية جدا وسهلة بقدر metaprogramming يذهب;-)...:
class Individualistic(object_or_whatever_bases):
def __init__(self, whatever_args):
self.__class__ = type('GottaBeMe', (self.__class__, object), {})
# keep rocking...!-)
أنا أيضا إضافة object
صراحة لأنه الحاجة (في بايثون 2.*
, و تقول هذا ما كنت تستخدم!!!) لكسب صفوف جديدة من نوع.أبدا استخدام تراث الطبقات أي أكثر من ذلك ، أنها لا تتصرف بشكل صحيح مع الاحترام إلى خصائص أخرى كثيرة إلى جانب (و التوافق لا يستطيعون-في بيثون 3, تراث الطبقات وأخيرا تم إبادة وذلك في كل فئة هو نمط جديد من دون اشتراط صراحة ترث من وجوه أي أكثر!).
الآن, أي واصف التي وضعت في 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)
لا شيء أسود-magicky كما ترى!-)
نصائح أخرى
أنا لا أفهم الطريقة التي كنت قد شيدت المثال الخاص بك ، ولا أفهم ماذا تعني "طبيعية" خصائص العمل فقط "على الطبقات".هنا هو كيف يمكنك إنشاء خاصية للقراءة فقط:
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__
.وبعبارة أخرى, الثعبان ليس روبي!
أنا بسعادة انتظار التصحيح من العظماء الثعبان metaprogrammer, ولكن أعتقد أنني على حق.
ليس واضحا ماذا تريد ؟ ولكن أفترض أنك تريد الكائنات.عرض أن تكون مخصصة لكل مثيل هنا هو وسيلة سهلة باستخدام عادي خصائص العرض الخاصية بإرجاع القيمة التي تم إرجاعها من قبل في حالة الاستدعاء
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
إذا رد لا يمكن أن تنتقل يمكننا أن إسناد ذلك إلى WidthVariable والتي ترجع العرض القائم على سبيل المثال
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