Home > OS >  python oop class attribute returns None when set
python oop class attribute returns None when set

Time:07-24

I'm trying to learn object orientated programming and when setting an attribute why does it return None?

Any tips on writing better code also appreciated... This is my class:

BEANS = ["black", "pinto"]
RICES = ["brown", "white"]
MEATS = ["chicken", "pork", "steak", "tofu"]


class Burrito:

    def __init__(self,
                meat,
                to_go,
                rice,
                beans,
                extra_meat=False,
                guacamole=False,
                cheese=False,
                pico=False,
                corn=False
                ):

        self.meat = self.setter("meat",meat)
        self.rice = self.setter("rice",rice)
        self.beans = self.setter("beans",beans)
        self.to_go = False
        self.extra_meat = False
        self.guacamole = False
        self.cheese = False
        self.pico = False
        self.corn = False

    def setter(self,category,attribute):

        print("category: ",category)
        print("attribute: ",attribute)

        if category == "meat":
            
            if attribute in MEATS:
                self.meat = attribute
            else:
                self.meat = False

        if category == "rice":
            
            if attribute in RICES:
                self.rice = attribute
            else:
                self.rice = False

        if category == "beans":
            
            if attribute in BEANS:
                self.beans = attribute

            else:
                self.beans = False
                
        else:
            self.category = "Error"

When I run this I expected the print to be False but returning None

noodle_burrito = Burrito("spagetti", True, True, False)
print("noodle_burrito.meat: ",noodle_burrito.meat)

And when I run this I expected the print to be tofu but returning None

vegg_burrito = Burrito("tofu", True, True, False)
print("vegg_burrito.meat: ",vegg_burrito.meat)

Thanks for any learning tips! Trying to reference this other SO post but I have never used super before.

CodePudding user response:

Any function that doesn't explicitly return anything implicitly returns None.

Your setter function internally sets things, but has no other return statement, so

self.meat = self.setter("meat",meat)

ends up setting self.meat to None right after self.setter has already set it to something.

You're also not doing anything with more than half of the parameters your constructor accepts. I would write your class as

BEANS = {"black", "pinto"}
RICES = {"brown", "white"}
MEATS = {"chicken", "pork", "steak", "tofu"}


def validate_attr(value, options):
    if value in options:
        return value
    return False


class Burrito:
    def __init__(
        self,
        *,
        meat,
        rice,
        beans,
        to_go,
        extra_meat=False,
        guacamole=False,
        cheese=False,
        pico=False,
        corn=False,
    ):
        self.meat = validate_attr(meat, MEATS)
        self.rice = validate_attr(rice, RICES)
        self.beans = validate_attr(beans, BEANS)
        self.to_go = bool(to_go)
        self.extra_meat = bool(extra_meat)
        self.guacamole = bool(guacamole)
        self.cheese = bool(cheese)
        self.pico = bool(pico)
        self.corn = bool(corn)

CodePudding user response:

Your setter sets the attribute, but then returns None, which you assign to the attribute again, overwriting whatever the setter itself assigned. Just drop the assignment in __init__.

def __init__(self,
            meat,
            to_go,
            rice,
            beans,
            extra_meat=False,
            guacamole=False,
            cheese=False,
            pico=False,
            corn=False
            ):

    self.setter("meat",meat)
    self.setter("rice",rice)
    self.setter("beans",beans)
    self.to_go = False
    self.extra_meat = False
    self.guacamole = False
    self.cheese = False
    self.pico = False
    self.corn = False

However, there's no reason for the setter method at all. Just assign values directly to the attributes.

class Burrito:

    def __init__(self,
                meat,
                to_go,
                rice,
                beans,
                extra_meat=False,
                guacamole=False,
                cheese=False,
                pico=False,
                corn=False
                ):

        self.meat = meat
        self.rice = rice
        self.beans = beans
        self.to_go = to_go
        self.extra_meat = extra_meat
        self.guacamole = guacamole
        self.cheese = cheese
        self.pico = pico
        self.corn = corn
  • Related