I'm trying to generate a dictionary with a lambda value and for some reason it isn't working as it should.
The bit in my code that is broken is:
def market():
clear()
# Creates the dictionary for use in menu.display
stock = {}
for obj in stuff.instances:
stock[f"{obj.name:<10} {obj.qty:<5} ${obj.price}"] = lambda: buy(obj) # <<<<<<<< this is whats broken
stock["Go back"] = lambda: main()
menu.display(menu("Here's what's in stock: \n "+"Name Qty Price", stock)) # creates a menu object with the stock and displays and runs the choice
So what's happening is: I am iterating through a list of objects created by a class, I am then adding to a dictionary, originally empty, with the key being some information about the object, and the value being a lambda function which calls another function called "buy()" with an argument of the object (This is what doesnt work.)
For some reason, for all choices, it will only "buy" the last object in the list. I don't believe this is an issue with the menu.display function itself as later, I add another key called "Go back" with a value of "lambda: main()" which works perfectly fine.
I have tested around and doing stuff such as replacing the lambda function with something like "obj.name" and printing it and that works fine. Its purely just that and I'm completely lost why.
Obviously this code won't work on it's own so I'm also going to include another snippet with all the relevant stuff to make it work and so that u can see whats kinda meant to be going on. I've put a comment saying "<<<<<< this is whats broken" so u dont miss the original thing, its near the end.
import random
from time import sleep
from replit import clear
# variables
money = 10000
inv = 0
# classes
class menu:
def __init__(self, text, menuDict):
self.text = text
self.menu = menuDict
# Displays the menu, gets the choice, and runs the relevant lambda
def display(self):
choice = " "
while ord(choice) < 65 or ord(choice) > 65 + len(self.menu): # checks if thing typed in is a valid choice
clear()
letter = 65 # chr(65) = A
# displays menu
print(self.text)
for key in self.menu.keys():
print("{}: {}".format(chr(letter), key))
letter += 1
choice = input().upper()
if len(choice) == 0 or len(choice) > 1: # ord() doesn't like strings of 0 length and strings > 1 length
choice = " "
choice = ord(choice) - 65
list(self.menu.values())[choice]() # Executes the chosen lambda within the dict
class stuff:
instances = [] # When you call drugs.instances, it will return a list of all
# the instances within the class
qtyVariation = 0.7
def __init__(self, name, basePrice, maxPriceRise, minPriceFall, baseQty):
self.name = name
self.basePrice = basePrice
self.maxPriceRise = maxPriceRise
self.minPriceFall = minPriceFall
self.baseQty = baseQty
self.price = basePrice
self.qty = 0
self.owned = 0
stuff.instances.append(self) # adds the obj just made to the class's list of instances
# probably irrelevant, same with method underneath
@classmethod
def randomise_prices(cls):
for obj in cls.instances:
if random.randint(0, 1): # Higher
obj.price = round(obj.basePrice * random.uniform(1, obj.maxPriceRise))
else: # Lower
obj.price = round(obj.basePrice * random.uniform(obj.minPriceFall, 1))
@classmethod
def randomise_qtys(cls):
for obj in cls.instances:
obj.qty = round(obj.baseQty * random.uniform(1 - cls.qtyVariation, 1 + cls.qtyVariation))
thing1 = stuff(name="thing1"
, basePrice=120
, maxPriceRise=1.4
, minPriceFall=0.8
, baseQty=5)
thing2 = stuff(name="thing2"
, basePrice=50
, maxPriceRise=2
, minPriceFall=0.8
, baseQty=10)
thing3 = stuff(name="thing3"
, basePrice=400
, maxPriceRise=1.2
, minPriceFall=0.7
, baseQty=3)
# funcs
def market():
clear()
# Creates the dictionary for use in menu.display
stock = {}
for obj in stuff.instances:
stock[f"{obj.name:<10} {obj.qty:<5} ${obj.price}"] = lambda: buy(obj) # <<<<<<<< this is whats broken
stock["Go back"] = lambda: main()
menu.display(menu("Here's what's in stock: \n "+"Name Qty Price", stock)) # creates a menu object with the stock and displays and runs the choice
def buy(item):
global money, inv
if item.qty <= 0:
print(f"Not enough {item.name} in stock.")
sleep(2)
elif item.price > money:
print("You cannot afford that.")
sleep(1)
else:
money -= item.price
item.qty -= 1
item.owned += 1
inv += 1
market()
def main():
clear()
print("hello i am main func")
sleep(1)
market()
if __name__ == "__main__":
stuff.randomise_prices()
stuff.randomise_qtys()
main()
Please ignore my frankly shitty code lol, first proper time trying to work with classes and all that so I dont know too much about them.
Anything would appreciated such as telling me I'm dumb and "wtf is happening in ur code" and that I should just approach it completely differently, and by all means do (I know I'm sorry! very new) but at least tell me what I'm doing wrong and how I could go about correcting it. Thanks!