Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
278 views
in Technique[技术] by (71.8m points)

python - Calculate attribute if it doesn't exist

I am trying to access an attribute that shouldn't be created in the __init__ method of my class but can be calculated by calling another method. I am trying to make it so that if I try to access the attribute and it does not exist it will be automatically calculated. However, I don't want it to be recalculated if the attribute does exist, even if the value would be different. For example:

class SampleObject(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def calculate_total(self):
        self.total = self.a + self.b

sample = SampleObject(1, 2)
print sample.total   # should print 3
sample.a = 2
print sample.total   # should print 3
sample.calculate_total()
print sample.total   # should print 4

My best solution so far is to make a get_total() method that does what I need.

class SampleObject2(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def calculate_total(self):
        self.total = self.a + self.b

    def get_total(self):
        if hasattr(self, 'total'):
            return self.total
        else:
            self.calculate_total()
            return self.total

sample2 = SampleObject2(1, 2)
print sample2.get_total() # prints 3
sample2.a = 2
print sample2.get_total() # prints 3
sample2.calculate_total()
print sample2.get_total() # prints 4

This is working fine, but I have read that using getters in python is discouraged and I was hoping to avoid calling this function every time I wanted to access the attribute. Is this my best solution, or is there a cleaner, more pythonic way of doing this?

This is an example that I made up. In my actual problem, calculate_total() is a time consuming process that won't necessarily need to be called. So I don't want to execute it in the init method.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You want to use the @property decorator. Create a method, that will be accessed like a normal attribute, that does lazy computation:

class SampleObject:

    def __init__(self):
        # ...
        self._total = None

    @property
    def total(self):
        """Compute or return the _total attribute."""
        if self._total is None:
            self.compute_total()

        return self._total

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...