python 3.x - returning a replaced field in a list of namedtuples in a namedtuple -
i have restaurant , dish type namedtuple defined below:
restaurant = namedtuple('restaurant', 'name cuisine phone menu') dish = namedtuple('dish', 'name price calories') r1 = restaurant('thai dishes', 'thai', '334-4433', [dish('mee krob', 12.50, 500), dish('larb gai', 11.00, 450)])
i need change price of dish 2.50. have following code:
def restaurant_raise_prices(rest): result = [] item in rest: dish in item.menu: dish = dish._replace(price = dish.price + 2.50) result.append(item) return result
it replaces price field , returns dish namedtuple:
[dish(name='mee krob', price=15.0, calories=500), dish(name='larb gai', price=13.5, calories=450)]
how can change code add restaurant well?
but returns dish. if wanted entire restaurant too? how can make change output is:
restaurant('thai dishes', 'thai', '334-4433', [dish(name='mee krob', price=15.0, calories=500), dish(name='larb gai', price=13.5, calories=450)])
named tuples first , foremost tuples, , such immutable. means cannot modify existing objects. if wanted change them, have create new tuples containing new values , replace references old tuple new tuple.
the code using not work that, since dish = dish._replace(…)
replace value of dish
new tuple, changing dish
references not update reference exists within restaurant tuple. also, line result.append(item)
being part of inner loop iterate on dishes, end multiple (unchanged!) copies of same restaurant tuple in result.
you change make work (btw. assuming pass single restaurant function—so need 1 loop dishes):
def restaurant_raise_prices (rest): dishes = [] dish in rest.menu: dishes.append(dish._replace(price=dish.price + 2.50)) rest = rest._replace(menu=dishes) return rest
this return new restaurant changed prices each dish (note r1
won’t reflect change):
>>> r1 restaurant(name='thai dishes', cuisine='thai', phone='334-4433', menu=[dish(name='mee krob', price=12.5, calories=500), dish(name='larb gai', price=11.0, calories=450)]) >>> restaurant_raise_prices(r1) restaurant(name='thai dishes', cuisine='thai', phone='334-4433', menu=[dish(name='mee krob', price=15.0, calories=500), dish(name='larb gai', price=13.5, calories=450)])
a cleaner way introduce proper types mutable, can make bit better. after all, restaurants objects can change: can modify menu time, without becoming new restaurant. makes sense have restaurants—as dishes—be mutable objects instead:
class restaurant: def __init__ (self, name, cuisine, phone): self.name = name self.cuisine = cuisine self.phone = phone self.menu = [] def __str__ (self): return '{} ({}) - {} ({} dishes)'.format(self.name, self.cuisine, self.phone, len(self.menu)) class dish: def __init__ (self, name, price, calories): self.name = name self.price = price self.calories = calories def raise_price (self, amount): self.price += amount def __str__ (self): return '{} (price: {}, calories: {})'.format(self.name, self.price, self.calories)
>>> r1 = restaurant('thai dishes', 'thai', '334-4433') >>> r1.menu.append(dish('mee krob', 12.50, 500)) >>> r1.menu.append(dish('larb gai', 11.00, 450)) >>> print(r1) thai dishes (thai) - 334-4433 (2 dishes) >>> dish in r1.menu: print(dish) mee krob (price: 12.5, calories: 500) larb gai (price: 11.0, calories: 450) >>> dish in r1.menu: dish.raise_price(2.50) print(dish) mee krob (price: 15.0, calories: 500) larb gai (price: 13.5, calories: 450)
Comments
Post a Comment