12 Replies - 679 Views - Last Post: 11 April 2019 - 02:47 PM Rate Topic: -----

#1 NantucketSleighride   User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 118
  • Joined: 13-February 11

Reassigning Parameter Variable within Function

Posted 07 April 2019 - 07:19 PM

I'm having a bit of a funky situation that's throwing me off.

I'm working on a goofy little project. It's going fairly well, but I'm really stuck with a strange thing that I'm not quite understanding.

I'm passing a list as a parameter and then possibly using that list to do various things. They're all working just fine except for one. When I "Load" - it reads from a file on my drive and sends back a list. When I try to reassign the variable I was using; it simply doesn't let me. It goes grey as if I'm using a new variable that's not being used.

I'm assuming it's not letting me do it, since I may reassign the variable to something I don't want it to be and the rest of the function could get screwed up? How do I get around this? I've tried a few things, but none of them work. The "Load" function works just fine - because I use it at the startup of the program to load the list in in the first place. Also - ignore the poor coding. I'm a novice and just trying to work on a little project I thought of.

Here's the code I'm using:
def ValidateCommand(command, gameList):
    command = str.lower(command)
    command = str.split(command)

    if command[0] == "load":  # load game file
        gameList = ReadFile()
    elif command[0] == "save":  # save game file
        SaveFile(gameList)
    elif command[0] == "new":  # create new game
        gameList.append(AddBoardGame())
    elif command[0] == "list" or command[0] == "display":  # displays gameList
        DisplayBoardGameList(gameList)
    elif command[0] == "sort":  # sorts the list
        if len(command) > 1:
            if command[1] == "player":
                SortList("max players", gameList)
        else:
            print ("Sorting List By Name...")
            SortList("name", gameList)
    elif command[0] == "delete":
        if len(command) > 1:
            command.pop(0)  # pops the command "delete" from the beginning
            command = " ".join(command)  # puts the rest of the commands into a single string for the game name
            DeleteGame(command,



It's that very start of the "if" statement... it acts as if the 'gameList' variable is new - instead of overriding the one I sent in as a parameter... But I want it to override that.

Python is confusing me - because I'm used to things like C# where I have to say what sort of variable I'm using and being able to do stuff like this... So I tried changing my Read function to take in a parameter and then just clearing that parameter as a list and then adding to the list. It's working OK.

I'm just not sure why I can't do it the way I want too, though.

This post has been edited by NantucketSleighride: 07 April 2019 - 07:35 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Reassigning Parameter Variable within Function

#2 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 513
  • View blog
  • Posts: 1,632
  • Joined: 27-December 13

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 12:41 AM

I hope I have understood your problem correctly.

In Python a function forms a 'scope'.

Variables assigned inside the scope are local to the scope.

You do this by gameList = ReadFile(); due to this statement, 'gameList' is local in the full function - i.e. it is a totally different list from the one you send in as argument.
NOTE: This is so even if line 6 is never executed (depends of command[0]). The local/global status is decided at compilation, not at run-time.

I'm not sure what your target is, you send a list as function argument and immediately overwrite it (if command[0] == "load"). Please clarify if you need more help.

I hope this will bring you forward, otherwise just come back here.
Was This Post Helpful? 1
  • +
  • -

#3 NantucketSleighride   User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 118
  • Joined: 13-February 11

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 06:19 AM

View PostDK3250, on 08 April 2019 - 12:41 AM, said:

I hope I have understood your problem correctly.

In Python a function forms a 'scope'.

Variables assigned inside the scope are local to the scope.

You do this by gameList = ReadFile(); due to this statement, 'gameList' is local in the full function - i.e. it is a totally different list from the one you send in as argument.
NOTE: This is so even if line 6 is never executed (depends of command[0]). The local/global status is decided at compilation, not at run-time.

I'm not sure what your target is, you send a list as function argument and immediately overwrite it (if command[0] == "load"). Please clarify if you need more help.

I hope this will bring you forward, otherwise just come back here.


I figured out a way to do it differently; but what's throwing me off is that in something like C# I could do that. The idea is that I'm sending it my list object - and then if the command was to "load" it would take that list object and "load" the list from the save file into it, overwriting whatever was in the list already.

It's just throwing my head for a loop as to why I can do everything else with that object such as appending to it, deleting from it, etc, but that one line is acting as if I'm trying to create an entirely new variable name. Is there some way in python then to force it to use the parameter if there is one of the same name, in situations like this?

I finally did what I mentioned in my edit, though, which was just make ReadFile() now take in a list, pass it there, and then just clear the list append to it cleanly from the save file.

This post has been edited by NantucketSleighride: 08 April 2019 - 06:31 AM

Was This Post Helpful? 0
  • +
  • -

#4 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 513
  • View blog
  • Posts: 1,632
  • Joined: 27-December 13

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 07:32 AM

Well, you are right.
You can modify a list, because the list type is mutable.
Buy if you assign (use the = operator) inside a scope, a whole new variable (different id) is created.
This is something very fundamental in python, - I'm not familiar with C# so I just take your word for the difference.

To your question about 'forcing' the variable: Yes, if you use the global keyword, the variable will stay the same.
'globals' are for many reasons often considered bad; and in large programs they should be avoided.
But in a small code and with an explaining comment (for your future you) it's a possible workaround.
Was This Post Helpful? 1
  • +
  • -

#5 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2735
  • View blog
  • Posts: 4,373
  • Joined: 21-June 11

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 07:51 AM

The premise of the first post is false. Variables have function scope in Python, so you can't create a variable that's local only to an if-statement. So the assignment on line 6 does not create a new variable - it assigns to the function parameter that's defined on line 1.
Was This Post Helpful? 1
  • +
  • -

#6 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 513
  • View blog
  • Posts: 1,632
  • Joined: 27-December 13

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 08:04 AM

I'm not sure what sepp2k says here. Maybe we say the same?

In principle the code is equivalent to this small sample code:
def test(abc):
    print(abc, id(abc))
    abc = 123  # assignment here
    print(abc, id(abc))

abc = 'xyz'
print(abc, id(abc))
test(abc)
print(abc, id(abc))

# Outputs:
xyz 1850393846704  # in main
xyz 1850393846704  # in function
123 1952105344  # in function after assignment
xyz 1850393846704  # back in main



Clearly the assignment creates a local variable with unique id.
Was This Post Helpful? 1
  • +
  • -

#7 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2735
  • View blog
  • Posts: 4,373
  • Joined: 21-June 11

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 08:24 AM

Variables don't have an id, objects do.

In your code there are two variables named abc: One is the parameter to test. It is local to test and is thus in scope from line 1 through 4. The other is global and its scope is from line 6 through the end of the program.

The assignment on line 3 does not create a new variable. It assigns to the parameter.
Was This Post Helpful? 1
  • +
  • -

#8 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2735
  • View blog
  • Posts: 4,373
  • Joined: 21-June 11

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 08:33 AM

To perhaps make things clearer to OP, who has a C# background:

This Python code:

def f(x):
  if x > 10:
    x = 10
  print(x)



is equivalent to the following C# code:

void f(int x) {
  if (x > 10) {
    x = 10;
  }
  Console.WriteLine(x);
}



So f(11) will print 10 and f(4) will print 4.

It is not, as all the talk about new variables might imply, equivalent to this:

void f(int x) {
  if (x > 10) {
    int x = 10;
  }
  Console.WriteLine(x);
}



In this version f(11) would print 11 (and the assignment on line 3 would have absolutely no effect because it creates a new variable). You can not recreate this effect in Python (without giving the inner x a different name). This is not something that happens in Python and it's not the cause of the issues you (OP) are having with your code.

Note that neither the Python version nor the C# version would change the value of any variables that are defined outside of the function. Re-assigning a variable only affects the variable itself - not any other variables that have previously pointed to the same object. Python does not have an equivalent of C#'s out parameters.

Also note that I've used numbers above to create a simple example, but the same would be true for lists or any other type.
Was This Post Helpful? 1
  • +
  • -

#9 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 513
  • View blog
  • Posts: 1,632
  • Joined: 27-December 13

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 09:15 AM

View Postsepp2k, on 08 April 2019 - 04:24 PM, said:

Variables don't have an id, objects do.


ok, but hopefully the incorrect wording of mine did not disturb the meaning.. :wheelchair:/>

View Postsepp2k, on 08 April 2019 - 04:24 PM, said:

The assignment on line 3 does not create a new variable. It assigns to the parameter.

Hm, you might be right; but, why then, does the id of the parameter object change...? :notify:/>
Was This Post Helpful? 1
  • +
  • -

#10 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2735
  • View blog
  • Posts: 4,373
  • Joined: 21-June 11

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 09:26 AM

A re-assignment makes a variable (potentially) point to a different object. When you call id(variable), you get the ID of the object that the variable is currently pointing to. So in the following code you'll get two different IDs (assuming some_object and some_other_object in fact refer to different objects):

x = some_object
print(id(x))
x = some_other_object
print(id(x)) # Prints a different id



(It doesn't matter whether x is a local or global variable here).

On the other hand, you can make two variables point to the same object and you'll get the same id:

x = some_object
print(id(x))
y = x
print(id(y)) # Prints the same id



So the ID of the object that the parameter originally pointed to does not change. You simply made the parameter point to a different object, so you now get a different object's ID. But that's not the same as creating a new variable. The same variable can point to different objects during it's life time.
Was This Post Helpful? 1
  • +
  • -

#11 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 513
  • View blog
  • Posts: 1,632
  • Joined: 27-December 13

Re: Reassigning Parameter Variable within Function

Posted 08 April 2019 - 12:24 PM

@sepp2k:
Ok, I get what you're saying and agree.
Can't help getting a bit frustrated that you professional guys (you, baavgai, jon.kiparsky, ..) always are more precise.
I actually do feel that I have a good understanding of python, but when it comes to the detailed explanations I'm only an amateur.

But let's look at the bright side of it:
My imperfections spark discussions like this, hopefully bringing knowledge and better understanding to many people.

Always look at the bright side of life... :wink:/> o_0/>
Was This Post Helpful? 1
  • +
  • -

#12 baavgai   User is offline

  • Dreaming Coder
  • member icon


Reputation: 7419
  • View blog
  • Posts: 15,373
  • Joined: 16-October 07

Re: Reassigning Parameter Variable within Function

Posted 09 April 2019 - 11:08 AM

I think I know where you're stuck.

Given this:
def thing(cmd_line, lst):
    cmd = cmd_line.lower().split()
    if cmd[0]=='push':
        lst.extend(cmd[1:])
    elif cmd[0]=='print':
        print(lst)
    elif cmd[0]=='clear':
        lst = []

a = []
thing("push x y", a)
thing("print", a)
thing("push z", a)
thing("print", a)
thing("clear", a)
thing("print", a)



I get this:
['x', 'y']
['x', 'y', 'z']
['x', 'y', 'z']


Oops, that clear didn't work. Probably the same way your load didn't work.

The reason is that we've replaced the list we passed with a new list, loosing the reference to the one that was passed. This would work exactly the same way in C#...

The fix is to work with the object passed and not loose track of it. e.g.
    elif cmd[0]=='clear':
        lst.clear()


Similarly, if you want to replace data, clear then load.

Hope this helps.
Was This Post Helpful? 1
  • +
  • -

#13 NantucketSleighride   User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 118
  • Joined: 13-February 11

Re: Reassigning Parameter Variable within Function

Posted 11 April 2019 - 02:47 PM

Hey, guys. Thanks all for the help. My head wasn't on straight when I was trying to do this - and thought C# handled it differently. I haven't coded in a long time - it's just a hobby for me that I pick up and drop periodically.

Anyway - I wasn't thinking correctly at how I was going about this and I realize what I was confusing myself with now.

When using the variable name to assign it to a new list - it creates a new list in memory and makes that variable reference that; which is find... But there's no reason for it to affect the old list - the old list stays in memory as long as something is referencing it; and when I pass the list into a function, the class that holds that list is still referencing it... But modifying the list with things like .Clear() or .Sort() work because the variable is referencing the list, as long as I don't reassign that variable to point to something else.

For some reason my brain wouldn't accept anything other than - the variable is stuck to the object and that trying to override it with "new" was how things worked... I have no idea why I couldn't see around it.

But thanks for the input!

I reinstalled Windows on my iMac and am digging into C# again; just messing around. But I tried this out on it and realized it didn't work and then this clicked in. I was having a massive brain fart with this one.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1