3

I have two classes. One class has an attribute x but not y, and the other class has an attribute y but not x.

I have a function that accepts either class as an argument. Is there a one-line way to assign a new variable to the x attribute if it exists, or the y attribute if not? I.e.,

if hasattr(input_object, 'x'):
    new_var = input_object.x
else:
    new_var = input_object.y

I thought I would be able to do:

new_var = getattr(input_object, 'x', input_object.y)

But that raises an AttributeError if the input_object doesn't have y, even though it does have x.

user2034412
  • 4,102
  • 2
  • 23
  • 22
  • 1
    What's wrong with your existing solution with the if/else? – BrenBarn Jul 16 '15 at 01:46
  • Nothing I guess - I'm doing this for a few different attribute pairs and I wanted to cut down on how many checks I have to do before I can just assign the values. – user2034412 Jul 16 '15 at 01:57

3 Answers3

3

You can use getattr for y too.

new_var = getattr(input_object, 'x', None) or getattr(input_object, 'y', None)
Utku Zihnioglu
  • 4,714
  • 3
  • 38
  • 50
  • 2
    Note that this may cause unexpected results if 'x' is explicitly set to None, or to any other boolean-false value (like zero). – BrenBarn Jul 16 '15 at 01:46
  • 1
    @BrenBarn, good point. I would go for an answer similar to larsks: ```input_object.x if hasattr(input_object,"x") else input_object.y``` – Utku Zihnioglu Jul 16 '15 at 01:50
3

Or you can use an if/else construct:

new_var = (
  input_object.x if hasattr(input_object, 'x')
  else input_object.y
)

This will not evaluate input_object.y unless there is no input_object.x.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • 2
    The advantage here is that you will still get an AttributeError for `input_object.y` if it does not exist AND `input_object.x` does not exist, if that is the behavior you want. utku.zih's answer will never raise an AttributeError, which is fine as long as you can do something sane with `None` or other static default. – larsks Jul 16 '15 at 01:41
  • 1
    No need to use `getattr` for `'x'`, you can do `input_object.x` just as you did for `y`. – BrenBarn Jul 16 '15 at 01:47
0

Nest the getattr call like so:

getattr(model, "field1", getattr(model, "field2", None))
Zoe
  • 27,060
  • 21
  • 118
  • 148
Otobong Jerome
  • 401
  • 6
  • 5