#πŸ”’ recursive __mul__ returning None (?)

67 messages Β· Page 1 of 1 (latest)

ionic hill
#
class Recipe:
    def __init__(self, data):
        self.ingredients = [Ingredient(items.get(i, Item(i)), j) for i, j in zip(data[0], data[1])]
        self._quantity = data[2]
        self.time = data[3]
        self.rate = self._quantity/self.time

        self.data = data

    def __mul__(self, multiplier: int):
        if not isinstance(multiplier, int): return self

        new_data = [self.data[0], list(map(lambda _: _*multiplier, self.data[1])), self.data[2]*multiplier, self.data[3]*multiplier]

        new_recipe = Recipe(new_data)

        for i in range(len(new_recipe.ingredients)):
            if new_recipe.ingredients[i].recipe is not None:
                new_recipe.ingredients[i].recipe *= multiplier

        return new_recipe
# Recipe format #

# [
#   [item names],
#   [item quantities],   
#   recipe yield,
#   recipe time
# ]

items['iron plate'].recipe = Recipe([['iron ore', 'copper plate'], [8,4], 5, 3])
items['iron ore'].recipe = Recipe([['a', 'b'], [1,2], 3,4])

items['a'].recipe = Recipe([['c'], [1], 2, 3])

when i try to multiple iron ore recipe, a recipe suddenly becomes None instead of multiplying as well pithink

severe atlasBOT
#

@ionic hill

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

dull summit
#

Shouldn't be possible with the code you show as far as I can see.

ionic hill
#

which is why im hella confused

dull summit
#

Show an example multiplication which gives None

ionic hill
#

items['iron ore'].recipe *= 3 is what i did

#
items['iron plate'].recipe = Recipe([['iron ore', 'copper plate'], [8,4], 5, 3])
items['iron ore'].recipe = Recipe([['a', 'b'], [1,2], 3,4])

items['a'].recipe = Recipe([['c'], [1], 2, 3])

items['iron ore'].recipe *= 3

print(items['a'].recipe)
items['iron plate'].dump()
#
PS C:\Users\Dagger> py good.py
None
5 iron plate +(1.67/s) @ 3s
  L 8 9 iron ore +(0.75/s) -(2.67/s) @ 12s
    L 3 a
    L 6 b
  L 4 copper plate
#

and this result

dull summit
#

Ok.

ionic hill
#

a recipe is None pithink

#

if i dont multiply

#

this result

#
PS C:\Users\Dagger> py good.py
5 iron plate +(1.67/s) @ 3s
  L 8 3 iron ore +(0.75/s) -(2.67/s) @ 4s
    L 1 2 a +(0.67/s) -(0.25/s) @ 3s
      L 1 c
    L 2 b
  L 4 copper plate
#

ye i got the dump thing working which is nice

#

last step is figuring out the multiplication bit

undone jewel
#

a bit off topic but you might want to look into dataclasses, it's not easy to read this code and it's not helping πŸ˜…

ionic hill
#

its just that with how recipes are encoded (cause needs to be serializable) i couldnt use one for this

#

well ig i could if i used dict instead of list

#

forgot about that again

dull summit
#

I'd break it up a bit. Maybe make:

items['iron ore'].recipe *= 3

into:

ore = items['iron ore'].recipe
print(type(ore),ore)
pre *= 3
print(3, type(ore), ore)
items['iron ore'].recipe = ore

possibly with some dumps. See where things go sour.

You can also:

from typeguard import typechecked
........
@typechecked
def __mul__(....) -> Recipe:
dull summit
ionic hill
#

which iss to be expected since issue is a recipe pithink

#

let me add prints for htat

#
<class '__main__.Recipe'> <__main__.Recipe object at 0x0000025D2844BD90>
<class '__main__.Item'> <__main__.Recipe object at 0x0000025D28780050>
3 <class '__main__.Recipe'> <__main__.Recipe object at 0x0000025D284BE2C0>
3 <class '__main__.Item'> None
ore = items['iron ore'].recipe
print(type(ore),ore)
print(type(items['a']),items['a'].recipe)
ore *= 3
print(3, type(ore), ore)
print(3, type(items['a']),items['a'].recipe)
#

ye its just something inside that __mul__

dull summit
#

Oh, hey, I hadn't notices that the None was from items['a'].

ionic hill
#

items['a'].recipe is None to be exact

#

but ye

dull summit
#

Should it be None?

ionic hill
#
items['a'].recipe = Recipe([['c'], [1], 2, 3])
#

no i set it on code

#

it becomes none after multiplying ore recipe

dull summit
#

Is items just a dict?

ionic hill
#

ye

#
items: dict[str, Item] = dict()
#

item name with its corresponding object

#
@dataclass
class Item:
    name: str
    rate: Rates = Rates(sys.maxsize, sys.maxsize) # absurd numbers to spot if something went wrong
    recipe: Optional[Recipe] = None

    def __post_init__(self):
        items[self.name] = self

this how stuff gets added to it

#

oh god damnit i see it now

#
    def __mul__(self, multiplier: int):
        if not isinstance(multiplier, int): return self

        new_data = [self.data[0], list(map(lambda _: _*multiplier, self.data[1])), self.data[2]*multiplier, self.data[3]*multiplier]

        new_recipe = Recipe(new_data)

        for i in range(len(new_recipe.ingredients)):
            print(new_recipe.ingredients[i])
            if new_recipe.ingredients[i].recipe is not None:
                new_recipe.ingredients[i].recipe *= multiplier

        return new_recipe

changing the mul to this printed

Ingredient(item=Item(name='a', rate=<__main__.Rates object at 0x00000200765BDA90>, recipe=None), quantity=3)
Ingredient(item=Item(name='b', rate=<__main__.Rates object at 0x00000200765BDA90>, recipe=None), quantity=6)
#

thats annoying

dull summit
#

This line:

                new_recipe.ingredients[i].recipe *= multiplier

Can you print i, new_recipe.ingredients[i] and new_recipe.ingredients[i].recipe before and after?

ionic hill
#

just need to figure out how to fix it

#

issue is when creating new_recipe

#

.-.

#
    def __mul__(self, multiplier: int):
        if not isinstance(multiplier, int): return self

        new_recipe = Recipe(self.data)
        new_recipe._quantity *= multiplier
        new_recipe.ingredients = self.ingredients

        for i in range(len(new_recipe.ingredients)):
            new_recipe.ingredients[i].quantity *= multiplier

        for i in range(len(new_recipe.ingredients)):
            # print(new_recipe.ingredients[i])
            if new_recipe.ingredients[i].recipe is not None:
                new_recipe.ingredients[i].item.recipe *= multiplier
#

this works

#

cool

dull summit
#

Hmm. Is this because Item('xxx') gets a .recipe=None ?

ionic hill
#

its because its not the same Ingredient() object anymore after i Recipe()

#

nvm yes u right

#

item

#

not ingredient

dull summit
#

BTWm you can change:

for i in range(len(new_recipe.ingredients)):
            new_recipe.ingredients[i].quantity *= multiplier

into:

for ingredient in new_recipe.ingredients:
    ingredient.quantity *= multiplier

and the same for the next loop. You don't need i.

ionic hill
#

i tried but it didnt mutate the array

#

which is what i want/need

dull summit
#

You're not mutating the array anyway.

#

That would only happen if you assigned to new_recipe.ingredients[i], which you don't.

ionic hill
#
5 iron plate +(1.67/s) @ 3s
  L need 8 produce 9 iron ore +(2.25/s) -(2.67/s) @ 4s
    L need 3 produce 6 a +(2.00/s) -(0.75/s) @ 3s     
      L 3 c
    L 6 b
  L 4 copper plate

anyways recipe multiplication thing works now so thats cool

dull summit
#

You're just mutating the objects inside the array;

severe atlasBOT
#
Python help channel closed for inactivity

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.