1

I need to check for empty values of every field of a distinct object. And I'm tiered of typing it out.

In this case. I have the an object called signal with multiple fields, which should not be empty.

if self.is_blank(signal.provider_id):
            error_response = "Signal rejected. No signal provider id given."
        elif self.is_blank(signal.sequence_id):
            error_response = "Signal rejected. No signal sequence id provided."

....

def is_blank (self, string):
        """Checks for None and empty values"""
        return True if string and string.strip() else False

Anyhow, what is the fast way in python to check all fields for "emptiness"? How do we loop them?

feder
  • 1,849
  • 2
  • 25
  • 43
  • 1
    Do you have a list of your fields? – Riccardo Bucco Aug 31 '22 at 07:31
  • Beware that `is_blank()` returns `True` if the string is **not** blank! You may either want to rename it, or add a `not` somewhere. I'd recommend rewriting `is_blank()` as `def is_blank(text): return not (text and text.strip())` – norok2 Aug 31 '22 at 08:08

3 Answers3

3

You may want to use operator.attrgetter:

def is_blank(self, field_names):
    for name in field_names:
        if getattr(self, name) and getattr(self, name).strip():
            return True, name
    return False, None

...

is_blank, name = self.is_blank(['provider_id', 'sequence_id', ...])
if is_blank:
    print(f'Signal rejected. No signal {name} provided.')

You can also implement is_blank with next:

def is_blank(self, field_names):
    return next(
        ((True, name)
         for name in field_names
         if getattr(self, name) and getattr(self, name).strip()),
        (False, None),
    )

This is going to print an error message for the first field that is failing the check. All you need to do is to provide a complete list of the attributes to be checked.

Riccardo Bucco
  • 13,980
  • 4
  • 22
  • 50
  • 1
    small copy/paste error. `ag = attrgetter(name)` should be `attrgetter` instead of `operator` – SargeATM Aug 31 '22 at 07:54
  • 1
    Why not just `getattr()`? I believe `attrgetter` is mostly useful in its starred form, as it lowers an otherwise explicit looping to a lower level. – norok2 Aug 31 '22 at 08:02
  • @norok2 You're totally right, I forgot about its existence. Let me fix it – Riccardo Bucco Aug 31 '22 at 08:11
  • 1
    Also perhaps worth mentioning that `dir(obj)` will provide the full list of `obj` attributes (including the private ones, that one may want to skip), in case one does not want to provide one explicitly. – norok2 Aug 31 '22 at 08:15
  • this is a better answer than mine – rostamn739 Aug 31 '22 at 09:01
1

To loop over all instance properties you use my_instance.__dict__

see this answer for details: Explain __dict__ attribute

rostamn739
  • 323
  • 3
  • 8
1

As rostamn mentioned, you can convert your object into a dictionary, after which you can loop through the (key, values) in a single line with a filter and check the result like so:

any_empty = any([True for x, y in your_obj.__dict__.items() if not y])

Change the condition in the loop to the type of empty check you need.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • okay, that is the more amazing shortcut i have ever seen in line of code. thank you – feder Aug 31 '22 at 09:21
  • I'd rather use `any()` and avoid creating the loop. Also `True if condition else False` is typically considered an anti-pattern. – norok2 Aug 31 '22 at 10:14
  • Ternary operators are very useful in many languages any make code **more** readable in my opinion. Python has many common patterns that I consider do consider anti-patterns. There are infinite ways of solving every problem. – Danny Varod Aug 31 '22 at 11:13
  • It is not the ternary operator the problem, the problem is that `True if condition else False` is typically better replaced by just `condition` or `bool(condition)` or, in this case, `any(condition)`, i.e. `any(True for x, y in your_obj.__dict__.items() if not y)` which has also the added advantage of not requiring the temporary memory to store the `list`. – norok2 Sep 02 '22 at 08:07
  • Any is indeed more efficient, casting a non boolean result to bool may work, but seems less readable. – Danny Varod Sep 04 '22 at 07:58