باستخدام خصائص محددة على سبيل المثال مستوى لا في الدرجة

StackOverflow https://stackoverflow.com/questions/1632170

  •  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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top