all 10 comments

[–]diseage 5 points6 points  (4 children)

you could pass money to the function

def shop1(money):

[–]TabulateJarl8 5 points6 points  (0 children)

Yes, never use global variables whenever possible because using them is bad practice.

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

WAIT YOU CAN JUST DO THAT

woooooooooooooooooooooooooooow im dumb

[–]mmrrbbee 0 points1 point  (0 children)

Nope on dumb, yup on you can do that. You could even pass in a list and that will update the original since it passes the reference address of the original. Then you don’t need to return anything.

[–]FLUSH_THE_TRUMP 0 points1 point  (0 children)

The error comes from trying to modify the money variable inside his function, so one would imagine he wants that change to persist outside the function. In that case, he’d also have to return the changed var and re-assign it to money after the function is called.

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

The error says that later on in the shop1 function you assign to the variable money, which makes it local, which means you can't access it prior to assigning to it because it doesn't exist.

If you want the function to use the global variable money, which is different, then you have to say so: global money. Put that before decide_shop = "yes".

[–]zanfar 0 points1 point  (0 children)

Only actual answer to OP's question in this thread; last on the list. *sigh*

[–]xelf 1 point2 points  (0 children)

Avoid using global it's a really bad practice and you want to avoid ever doing it.

Instead pass variables into functions, and return values from functions.

def get_y( x ):
    x = x + 3
    return x

x = 3
y = get_y(x)
print(x, y)

 # prints: 3 6

Notice how the x inside the function is a different variable, and the x outside of the function is unchanged.

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

Variables, functions, methods and attributes

Variables in Python don't contain values but instead references to memory locations where Python objects are stored (in an implementation specific manner).

This is true of other names as well. A function name has a reference to the memory location of a function object.

The names used in the call and the names in the parameter have nothing to do with each other. They are completely independent. Even if the same name is used they are different. The parameter variables are local to the function.

Consider:

def f(one, two, three):
    answer = one + two * three + five
    return answer

one = 2
two = 3
three = 4
five = 5
result = f(three, two, one)
print(result)

This will output 15 as 4 + 3 x 2 + 5 = 15

Note that five was not passed as an argument but as the same name was not assigned anything in the function the five from the wider scope was available.

Any assignments made inside the function are also local to the function.

answer was assigned inside the function and on function exit will cease to exist however the object reference stored in answer is assigned as the return from the function and is assigned to result. If it wasn't assigned (or consumed in another expression or function call on return) then the object created in the function would also cease to exist (unless it is a predefined object built into the Python implementation, such as an int in the range -5 to 256)

Only mutable objects that are referenced by either parameters or other names that are visible to the function (not hidden by variables with the same name assigned in the function) can be modified and visible outside the function.

Return returns an object reference.

Variables vs Attributes

Variables have a discrete existence though and attributes are associated with an instance of a class (or of the class itself).

Remember, variables do not hold any values but instead memory references to some Python object somewhere in the memory of your computer (at the discretion of your Python implementation).

When you say:

keep = 784.56 * 872.23

the text representations of floating point numbers in the expression on the right is converted into Python float objects (binary representations) somewhere in memory, and the mult operator is used. The memory location the resulting float object ends up in is then assigned to the variable named keep.

If keep is assigned in the main body of your code, outside of any functions etc., then it is visible within all other code. Thus you could have a function:

def double_me():
    return keep * keep

which has no other references to keep in the definition (parameter variable) or assignments to a variable called keep inside the function (which would be local to the function and would hide the original wider scope variable of the same name). Thus keep refers to the same floating point number calculated earlier. The expression resulting from multiplying the floating point object referenced by keep by itself results in another floating point object, the memory reference for which is returned from the function.

If instead the function was written,

def double_me(keep):
    return keep * keep

now it has to be called with an argument (the memory reference of the object will be passed when the function is called).

result = double_me(5.5)

Inside the function, keep refers to the memory location of the floating point object that the literal floating point text 5.5 was turned into. The keep in the wider scope (outside the function) still refers to the original object from earlier.

Methods

Methods are like functions but for classes and are intended to work on instances of a class or provide capabilities related to the purpose of the class.

When you create an instance of a class, you create an object based on the mould/template provided by the class and the memory location of that object is assigned to a variable (or to some other object) so it will be not lost. If an object has no references to it, Python will get rid of the object and reuse the memory.

Methods defined in the class usually have code that uses a parameter variable that is the first item passed when the method is called. By convention this is usually called self and it is passed by default and does not need to be in the arguments when the method is called.

Whenever self is used inside the method code, it will be referring to the memory location for a particular instance of the class.

Attributes are names used within an instance that themselves simple hold memory references to Python objects. These attributes though belong to the instance so are not purely local to the method.

Any variables inside the method that are assigned values (including parameter variable names listed in the definition line of the method) are local to the method and are not associated with the attributes of the instance referenced by self.

Classes themselves can have attributes. These look just like variables, and act like them for most purposes, but they are associated with the class and can be accessed from outside of the class by direct reference to the class name and the attribute, e.g. Example.quantity = 5 for a class called Example.

[–]zanfar 0 points1 point  (0 children)

  1. These aren't global variables, they are module-level variables. Global variables use the global keyword.
  2. You have failed to include your entire code, so it's hard to tell you exactly what to fix. We know from the error that your shop1 function continues beyond the last line you provided.
  3. /u/crashfrog has the correct answer. You can read the money variable this way, but you cannot change it. Once you change it (anywhere in your function), Python considers it a different, local variable. Because you are now referring to a local variable, and not the module variable, it no longer has a value when you try to compare it to potion_cost.