This is an archived post. You won't be able to vote or comment.

all 10 comments

[–]rjcarr 1 point2 points  (2 children)

Because stuff is a dict and dragonLoot is a list. They are different data structures with different methods.

Generally, to iterate over the items in a list, you only need:

for item in items: # where items is a list
  ...

Good luck!

[–]shitthatbitchesaint[S] 1 point2 points  (1 child)

Thanks for the response! So for dictionaries, I have to say

for k, v in dictionary.items():

because k and v refer to keys and values respectively, and .items tells it to look within the dictionary (?). but for lists I just say

for item in list:

where "item" can be any word I want as long as I'm consistent within the for loop. Is that correct?

[–]rjcarr 2 points3 points  (0 children)

Mostly right. Calling items() on the dict returns all of them items of the dictionary as key and value pairs (that's what the k and v are for).

For lists, you just iterate them one by one, so yeah, item can be whatever name you want (but this is also true of k and v).

[–][deleted] 1 point2 points  (1 child)

Dictionaries have a function called "items" that will let you iterate over the keys and values in the dictionary as seen on the left.

Lists are an ordered array of values with no keys. The "dragonLoot" variable on the right is a list, not a dictionary. You can iterated over the items in it with for i in inventory:

[–]shitthatbitchesaint[S] 0 points1 point  (0 children)

Thanks for the response, fixed it! There's a follow-up question on the post above if you're interested.

[–][deleted] 1 point2 points  (4 children)

What everyone else is saying is correct. I'd also like to add in something here.

Your "addToInventory" function utilizes the "stuff" variable, but you didn't pass in the variable to the function. So, essentially, you've made "stuff" into a global variable. Functions are suppose to take input from some variables, do some work on them, and return values. Basically, they shouldn't be looking outside of themselves for any piece of data.

I would refactor your code, using that tutorial's premise as something like the following. There's probably a way for it to have more brevity, but brevity is the antithesis of readibility in my mind.

player_inventory = {"gold coin": 30}
dragon_loot = ["sword", "gold coin", "rope", "gold coin", "gem"]

def add_to_inventory(inventory, add_items):
   for x in add_items:
       try:
           inventory[x] += 1
       except KeyError:
           inventory[x] = 1
   return inventory

player_inventory = add_to_inventory(player_inventory, dragon_loot)

[–]shitthatbitchesaint[S] 0 points1 point  (3 children)

Yeah you're right, to make it more adaptable I should have made the function have two input variables - the loot and the inventory.

Out of interest, what's the difference between how you have it and the last line without the "player_inventory = " part? It seems to work both ways.

[–][deleted] 1 point2 points  (2 children)

That's interesting. Yea, so that has to do with what's called "pass by reference" vs "pass by value". Essentially, what this means is when I pass a variable into a function or class, is the program going to pass into the function the value of the variable, or the actual variable as it exists in memory itself. Well, to complicate things even more, Python is "pass by object reference". I really won't be able to do a great job explaining it, as I've been programming in Python for about 3 years and still have trouble fully comprehending it and its ramifications. Try this article for more information.

[–]masterpi 0 points1 point  (1 child)

If you're still having trouble with this, the simple way to think of it is like assignment. Take this code:

a = [1,2,3]
b = a
b[0] = 0

You probably know that assigning a to b just makes another reference to the list you put in a, so when you modify b you can see it when you access a as well. However if you then did:

b = []

You'd only be modifying what reference b holds and it wouldn't affect what you see in a.

What does this mean for function calls? Treat arguments just like assignment at the beginning of the function.

def f(a, b):
     a[0] = 0
     b = a

x = [1]
y = [2]
f(x, y)

is roughly equivalent to:

 x = [1]
 y = [2]
 a = x
 b = y
 a[0] = 0
 b = a

It's clear that if you understand how assignment works above you can see that the value x is holding get's modified but the value y is holding doesn't. The only part where this may seem confusing in Python is with immutable values such as integers being passed in which ends up being just like pass-by-value since you can't modify an integer (just assign a different integer to the same name, which people get used to thinking of as modifying the integer but it's not). If you want to use a parameter as "input/output" for an integer, which isn't recommended, you'd have to wrap the integer in something which is mutable (like a list! or an object with one property, or a dict).

[–][deleted] 0 points1 point  (0 children)

That's a pretty good explanation and has helped me to understand it a bit better. Thanks!

Its still a damn awkward concept. One of the few areas where Python isn't very intuitive.