طريقة بيثوني للعمل فقط لأول مرة يتم استدعاء متغير

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

سؤال

يحتوي فئة Python الخاصة بي على بعض المتغيرات التي تتطلب عملًا لحساب المرة الأولى التي يتم استدعاؤها. يجب على المكالمات اللاحقة مجرد إرجاع القيمة المسبقة.

لا أريد أن أضيع الوقت في القيام بهذا العمل إلا إذا كان المستخدم بحاجة إليه بالفعل. فهل هناك طريقة نظيفة لتنفيذ حالة الاستخدام هذه؟

كانت فكرتي الأولية هي استخدام Property () لاستدعاء وظيفة في المرة الأولى ثم تجاوز المتغير:

class myclass(object):
    def get_age(self):
        self.age = 21 # raise an AttributeError here
        return self.age

    age = property(get_age)

شكرًا

هل كانت مفيدة؟

المحلول

class myclass(object):
    def __init__(self):
        self.__age=None
    @property
    def age(self):
        if self.__age is None:
            self.__age=21  #This can be a long computation
        return self.__age

ذكر أليكس أنه يمكنك استخدامه __getattr__, ، هذه هي الطريقة التي يعمل بها

class myclass(object):
    def __getattr__(self, attr):
        if attr=="age":
            self.age=21   #This can be a long computation
        return super(myclass, self).__getattribute__(attr)

__getattr__() يتم استدعاؤه عندما لا توجد السمة على الكائن ، أي. في المرة الأولى التي تحاول الوصول إليها age. في كل مرة بعد ، age موجود __getattr__ لا يتم استدعاؤه

نصائح أخرى

property, ، كما رأيت ، لن تسمح لك بتجاوزه. تحتاج إلى استخدام نهج مختلف قليلاً ، مثل:

class myclass(object):

    @property
    def age(self):
      if not hasattr(self, '_age'):
        self._age = self._big_long_computation()
      return self._age

هناك مناهج أخرى ، مثل __getattr__ أو فئة واصف مخصصة ، ولكن هذا هو أبسط!-)

هنا ديكور من كتاب طبخ بيثون لهذه المشكلة:

class CachedAttribute(object):
    ''' Computes attribute value and caches it in the instance. '''
    def __init__(self, method, name=None):
        # record the unbound-method and the name
        self.method = method
        self.name = name or method.__name__
    def __get__(self, inst, cls):
        if inst is None:
            # instance attribute accessed on class, return self
            return self
        # compute, cache and return the instance's attribute value
        result = self.method(inst)
        setattr(inst, self.name, result)
        return result

نعم ، يمكنك استخدام الخصائص ، على الرغم من أن التقييم البطيء يتم إنجازه أيضًا باستخدام الواصفات ، انظر على سبيل المثال:

http://blog.pythonisito.com/2008/08/lazy-descriptors.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top