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