Hamish Currie
Hamish Currie

Reputation: 501

Execute a number of functions keeping track if any returned true

I'm writing the code to take data from a html form and modify a database object. I only want to do a put() on the database object if there were changes, so I need to know if anything changed.

I've tried a couple of ways so far that I'll illustrate in code. They all use the following setup code:

def _addFormAttrToModel(self, obj, attr_name, new_attr):
    if hasattr(obj, attr_name):
        current_attr = getattr(obj, attr_name)
        if current_attr == new_attr:
            return False
    setattr(obj, attr_name, new_attr)
    return True
def addFormStringToModel(self, obj, attr_name):
    new_attr = self.request.get(attr_name, None)
    return self._addFormAttrToModel(obj, attr_name, new_attr)

The first uses or to decide if any of the method calls return True.

updated=False
updated = self.addFormStringToModel(customer, "name") or updated
updated = self.addFormStringToModel(customer, "addr") or updated
updated = self.addFormStringToModel(customer, "phone") or updated
if updated:
    customer.put()

Another form that I have experimented with uses a set:

results= set()
results.add( self.addFormStringToModel(customer, "name"))
results.add( self.addFormStringToModel(customer, "addr"))
results.add( self.addFormStringToModel(customer, "phone"))
if True in results:
    customer.put()

What I'd really love to do is something like this:

updated = self.addFormStringToModel(customer, "name") and \
          self.addFormStringToModel(customer, "addr") and \
          self.addFormStringToModel(customer, "phone")
if updated:
    customer.put()

However that stops execution after the first attribute that was updated. Is there a more pythonic way?

Upvotes: 1

Views: 27

Answers (2)

Klaus D.
Klaus D.

Reputation: 14369

In order to remove the redundant code you should first define the list of fields to check:

fields_to_check = ['name', 'addr', 'phone']

Then you use a list aggregation to apply the method to all values:

updated = [self.addFormStringToModel(customer, field) for field in fields_to_check]

The any() will tell if anyone of the results in the lis tis true:

if any(updated):
    customer.put()

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599708

Use any with a list:

updated = [self.addFormStringToModel(customer, "name"),
          self.addFormStringToModel(customer, "addr"),
          self.addFormStringToModel(customer, "phone")]

if any(updated):

You could make this shorter with a list comprehension:

updated = [self.addFormStringToModel(customer, field)
           for field in ('name', 'addr' 'phone')]
if any(updated)

Upvotes: 2

Related Questions