pythonoopattributespython-object

Pythonic way to get either one of two attributes from a Python object


I want to get either one of two attributes from a Python object. If neither of those attributes is present, I want to get a default value.

For instance, I want to get either the number of apples or of oranges in a FruitBasket, and if neither is present, I want to set n_fruits to 0 (because I am not interested in other fruits).

fruit_basket = FruitBasket(bananas=5)
try:
    n_fruits = getattr(fruit_basket, "apples")
except AttributeError as err:
    n_fruits = getattr(fruit_basket, "oranges")
except AttributeError as err:
    n_fruits = 0

This code breaks if there are neither apples or oranges:

AttributeError("'FruitBasket' object has no attribute 'oranges'")

The class FruitBasket can hold only one type of fruit. There is no risk that both apples and oranges are present. Even if that was the case, I still would store in n_fruits the first type of fruit (apples, in this case).

I want an elegant Pythonic way to solve this task: I have in mind many possible solutions, but all of them are ugly and convoluted!

By the way, FruitBasket is just an example. I am actually trying to get the centroids from a scikit-learn clusterer. KMeans and MeanShift algorithms store the centroids in the 'clusters_centers_' attribute, and GaussianMixture stores it in the 'means_' attribute (for my purposes, they are the same). If neither of them is present (in case of other clustering algorithms), I want to set centroids to an empty list.


Solution

  • you code breaks because you need to do add an additional try-except when there is an exception:

    fruit_basket = FruitBasket(bananas=5)
    try:
        n_fruits = getattr(fruit_basket, "apples")
    except AttributeError as err:
        try:
            n_fruits = getattr(fruit_basket, "oranges")
        except AttributeError as err:
            n_fruits = 0
    

    A better way would be to just set a default value to the getattr:

    fruit_basket = FruitBasket(bananas=5)
    n_fruits = getattr(fruit_basket, "apples", None)
    if n_fruits is None:
        n_fruits = getattr(fruit_basket, "oranges", 0)