简体   繁体   中英

How to make a function change variables while in a while loop?

def lol(done, really_done):
    done = done + 1
    print(done)
    if done == 10:
        really_done = True

really_done = False
while really_done == False:
    done = 0
    lol(done, really_done)

so whenever I run this code, it does not change the value of done, it always stays at 1. I want it to change to 10 and stop the while loop. I only want it in this type of module.

The general problem is that you want to save the state of done and really_done across calls to lol . There are several ways to do this, so I'll toss in another possibility.

A common way to keep state for a function is with a class:

class Lol:

    def __init__(self, done=0, max_done=10):
        self.done = done
        self.max_done = max_done

    @property
    def really_done(self):
        self.done >= self.really_done

    def lol(self):
        self.done += 1

lol = Lol()
while not lol.really_done:
    lol.lol()

The really_done variable inside the lol function and the really_done variable at the module level live in different scopes (also commonly called namespaces ). The former is a local variable and the latter is a global variable .

def lol(done, really_done):
    done = done + 1               ---+
    print(done)                      |
    if done == 10:                   +--- the local scope (inside a `def`)
        really_done = True        ---+

really_done = False               ---+
while really_done == False:          |
    done = 0                         +--- the GLOBAL scope 
    lol(done, really_done)        ---+

You can not signal to the while loop that you want to exit in this way, because the local scope is isolated from the GLOBAL scope. Instead, the function will need to signal to the caller that you're really done by using a return value:

def lol(done, really_done):
    done = done + 1
    print(done)
    if done == 10:
        really_done = True
    return done, really_done

done = 0
really_done = False
while really_done == False:
    done, really_done = lol(done, really_done)

Using the return value allows information from the local scope (function namespace) to be passed back out to the global scope (module namespace). This is similar to the same way that passing in arguments to a function allows information from the outer scope (module namespace) to be received as information in the local scope (function namespace).

You are resetting the value of done everytime you run the loop. Not only that - you're trying to change the value a global variable, but is instead changing the value of a simple parameter, so lol(done) isn't actually doing anything.

If you want to keep it in a function, you should use the keyword global to indicate you're using the global variables:

def lol():
    global done
    global really_done

    done += 1
    really_done = done == 10

really_done = False
done = 0
while not really_done:
    lol()

This should work, but it's bad code - you shouldn't use global if it's not a real need . Not changing much of your code, you could use return to keep your code cleaner:

def lol(done, really_done):
    done += 1
    really_done = done == 10

    return done, really_done

really_done = False
done = 0
while not really_done:
   done, really_done = lol(done, really_done)

That makes it a bit better. Yet, we could solve everything by simply looping a range with a for :

done = 0
for n in range(10):
    done += 1
print(done)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM