10

I am trying to change a variable further down the program. I have a global variable declared at the start of the program and I want to change the variable in different functions down the program. I can do this by declaring the variable inside the function again but I would like to know is there a better way of doing this. Some test code is below to explain what I mean.

ID = 'No'
project = ("Yep"+ID) # ID added with 'No' value which I later want to change

def pro():

    ID = "YES"
    print ID

def pro1(ID):

    # I could declare project again to get this to work, but I would like to avoid this
    print project # I want this to print with the new ID number.

if __name__ == '__main__':
    pro()
    pro1(ID)

Has anyone any ideas, thanks

I have tried the global variable but when I do this the project variable still prints out YepNo instead of YepYES. I want the new variable from the function proto change the variable in the project variable.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
chrisg
  • 40,337
  • 38
  • 86
  • 107
  • do you want the value of project to change as well? if this is the case, then you should make a class for it. – Ritwik Bose Jan 11 '10 at 10:07
  • 3
    Not related to the question, but I am kind of weirded out by your setting the local "myObject" to the return value of functions that have no return statement. That works (the value is set to None), but it's pointless, a WTF, and makes one think "what the hell was thinking he was doing". – ddaa Jan 11 '10 at 10:12
  • 2
    strings are immutable in Python. When doing string concatenation, as in your "project" assignment, you're creating a new string. There's no way you can change "project" later by changing the value of ID. – Alan Franzoni Jan 11 '10 at 10:13
  • 3
    Please do not put `if __name__ == '__main__':` more than once. Please. – S.Lott Jan 11 '10 at 11:14
  • 1
    Also, what does "predeclared variable" mean? Python has no declarations, so the title doesn't make any sense. – S.Lott Jan 11 '10 at 12:06

6 Answers6

12

To update global variables you could use

global ID
ID="Yes"

before assigning variable to ID = "YES"

But changing ID will be no effect on project variable, project = ("Yep"+ID), because project is already a string

you need to make a function like

def getprojectname(ID):
    return project+ID

The whole program may be like this

UPDATE: ... removed

YOU
  • 120,166
  • 34
  • 186
  • 219
  • To change a global variable, you should declare it as global. –  Jan 11 '10 at 10:43
  • 2
    I think the code style of this example is really bad... even though you answer the question, you are encouraging an improper programming. – Alan Franzoni Jan 11 '10 at 11:41
  • 1
    Yes, thats right and I know, I just didnt want to touch his codes, removed those now. – YOU Jan 11 '10 at 11:47
7

Beware, you're doing it wrong multiple times.

Even though you could use the global statement to change a global (it is discouraged since it's better to use function parameters and return values), that would NOT change other already assigned values. E.g. even though you reassign ID, you would NOT reassign project. Also: your functions return nothing, there's no point in assigning a name to their return value, and it's a BAD habit using an all-uppercase name (ID) for a variable since it's a convention to use them for constants.

This should clarify you the way global works:

myid = ''
project = ("Yep"+myid) #ID added with no value which I later want to change

def mutate_id():
    global myid
    myid = "YES"

def mutate_project():
    global project
    project = ("YEP" + myid)

if __name__ == '__main__': 
    print "myid", myid
    print "project ", project
    print

    mutate_id()

    print "myid", myid
    print "project ", project
    print

    mutate_project()

    print "myid", myid
    print "project ", project
    print

But the best way is to do WITHOUT globals:

def get_new_id(old):
    return "YES"

def get_new_project(old):
    return ("YEP" + myid)

if __name__ == '__main__': 
    myid = ''
    project = ("Yep"+myid) 

    print "myid", myid
    print "project ", project
    print

    myid = get_new_id(myid)

    print "myid", myid
    print "project ", project
    print

    project = get_new_project(project)

    print "myid", myid
    print "project ", project
    print

This will make all code interaction clear, and prevent issues related to global state change.

Solomon Ucko
  • 5,724
  • 3
  • 24
  • 45
Alan Franzoni
  • 3,041
  • 1
  • 23
  • 35
  • To expand on one minor point: `project = ("Yep"+ID)` is evaluated immediately: the variable `ID` is expanded to the string `'No'`, which is appended to `"Yes"` to make the string `'YepNo'`, which is immediately assigned to the variable `project`. Changing `ID` later has no effect because `project` already has its value. – James Polley Jan 11 '10 at 10:18
  • Yes, I commented on it directly on the OP post about that :-) – Alan Franzoni Jan 11 '10 at 11:39
2

Use the global statement.

The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals.

Example: http://www.rexx.com/~dkuhlman/python_101/python_101.html#SECTION004340000000000000000

P.S.

But don't use global too often, see http://www.youtube.com/watch?v=E_kZDvwofHY#t=10m45

miku
  • 181,842
  • 47
  • 306
  • 310
  • This only solves *some* of the problems with this code: for instance, it doesn't change the fact that `project` is assigned its value on the 2nd line and never changes, and part of what the OP wants is for `project` to be updated when `ID` changes. – James Polley Jan 11 '10 at 10:20
  • The link seems to be broken. – Matteo Monti May 25 '23 at 14:09
1

In your code you have two problems. The first about changing ID variable, which could be solved by using global.

The second that your code calculate project string and after that project don't know about ID.

To avoid code duplication you can define function to calc project.

So we have:

ID = 'No'
def GetProject():
    return "Yep"+ID

def pro():
   global ID
   ID = "YES"
   print ID

print GetProject()

pro()

print GetProject()
ton4eg
  • 1,372
  • 1
  • 10
  • 10
-1

You can mutate without reassigning:

variables = {}
def pro():
    if variables['ID'] == '':
        variables['ID'] = 'default'
wisty
  • 6,981
  • 1
  • 30
  • 29
-1

Why not use a dictionary?

>>> attr = {'start':'XXX', 'myid':'No'}
>>> 
>>> def update_and_show(D, value = None):
...     if value:  D['myid'] = value
...     print D['start'] + ' ' + D['myid']
... 
>>> update_and_show(attr)
XXX No
>>> update_and_show(attr, 'Yes')
XXX Yes
>>> update_and_show(attr, 'No')
XXX No
>>>
telliott99
  • 7,762
  • 4
  • 26
  • 26