2

Consider this simple code, which stores a few properties of a MyClass() object in a list:

c = MyClass()
props = [c.property1, c.property2, ..., c.propertyN]

Now, under the hood, c.property1..N are realized as @property-decorated getter functions, which may raise exceptions during execution. In that case, I want to use a default value ('n/a') in the list assignment, instead of the inaccessible property value.

But I don't want to skip the entire list assignment altogether. So, if only c.property2 causes an exception, the result should still be:

props = ['value_of_property1', 'n/a', ..., 'value_of_propertyN']

So I cannot wrap the try-except around the entire list assignment:

c = MyClass()
try:
   props = [c.property1, c.property2, ..., c.propertyN]
except MyException:
   props = # yes, what?

Of course I could try-except for each element individually:

c = MyClass()
props = []

try:
    props.append(c.property1)
except MyException:
    props.append('n/a')

try:
    props.append(c.property2)
except MyException:
    props.append('n/a')

# repeated N times

... but this bloats the code and doesn't feel right.

Is there some sort of inline exception handling?

Perhaps similar these inline if-else statements:

props = [c.property1 if len(c.property1) else 'n/a',
         c.property2 if len(c.property2) else 'n/a',
         ...
         c.propertyN if len(c.propertyN) else 'n/a',
        ]

Notes:

  • I have full control over the code for MyClass() and the getter functions.

  • Modifying the getter functions to handle exceptions internally and return a default value straight away is not an option, because in other situations I want to know (via exception...) if the property is accessible or not. Otherwise how could I tell if 'n/a' was the true value of a property or the replaced default (fallback) value?

  • I have the same problem in print statements using (N*'{};').format(c.property1, c.property2, ..., c.propertyN)

rikinet
  • 93
  • 6
  • For the `print` problem, use `print(*props, sep=';')`. – Aran-Fey Aug 23 '19 at 09:15
  • See also: https://stackoverflow.com/questions/1215408/how-to-list-all-class-properties – quamrana Aug 23 '19 at 09:28
  • @Aran-Fey Yes - as long as `props` already exists and the intended output formatting is as simple as in above example. So do you recommend creating the list first (using the `getattr()` loop from your answer below), and then print elements from the list, rather than the properties directly? – rikinet Aug 23 '19 at 09:31

1 Answers1

1

There is no inline exception handling, but there's something better: loops. None of your code is DRY, but that's easily fixed with a loop:

c = MyClass()
props = []
prop_names = ['property1', 'property2', ...]

for prop_name in prop_names:
    try:
        value = getattr(c, prop_name)
    except MyException:
        value = 'n/a'

    props.append(value)

If you need to do something more complex than just access an attribute, you can replace the list of property names with a list of functions:

c = MyClass()
props = []
getters = [lambda c: c.property1, lambda c: c.property2, ...]

for getter in getters:
    try:
        value = getter(c)
    except MyException:
        value = 'n/a'

    props.append(value)
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149