How To End A Loop When A Condition is Satisfied? - python

As per my previous question here, my question today is related to it. I have a constantly updating global variable, and I pass that variable to a function. That function consists of a loop and conditional statements. I want the loop to end when the condition is satisfied, but it keeps on looping.
Here is my code.
class LetterAScreen:
def identity(self):
global where
lol=Identifier()
lol.fn_compare()
print where
def verifier(self):
global where
verify=where
if verify != 1:
while (count>0):
print ("try again")
run=LetterAScreen()
run.identity()
run.verifier
print ("try again")
count += 1
else:
print ("correct")
The "Correct" is when the variable turns to one. Otherwise, it is not correct and the user should try again. The output ends up looking like this.
#incorrect inputs
19
try again
try again
19
try again
try again
19
try again
try again
19
try again
try again
19
try again
try again
#correct inputs but loop doesn't end
1
try again
try again
1
try again
try again
1
try again
try again
1
try again
try again
The essential part about Identifier class is only the updating variable. I believe the problem is with the class I've shared. I'm really unfamiliar how this works. I hope you could help me.

There are some things to note here:
Why are your creating a new LetterAScreen object in your loop?
Be carefull when using a global variable, usually there are other ways to solve this cleaner.
I don't know what the Identifier class does but guess the fn_compare function of that class will change the where variable? Also, creating a new Identifier on every call of the identity function seems something you should change.
That being said, the verifier method needs to be adjusted as followed:
def verifier(self):
global where
count = 1
while (count>0 and where != 1):
print ("try again")
self.identity()
count += 1
print ("correct")
You shouldn't assign the global where variable to a local one, this will cause problems because the local one will not be updated in the loop. You can compare to this global where variable directly. Also I removed the run variable, you are executing in an instance of the LetterAScreen class so you can call the identity method on the self object (similar to a this in JS).

first of all you probably don't need to create new instance inside a method "verifier" (methods are already called when the instance is created, you can access the instance using "self" variable.
So instead of
run=LetterAScreen()
run.identity()
write
self.identity()
also instead of of using complex "global" approach
you can create instance variable like self.verify and change it inside "identify"
class LetterAScreen:
def __init__(self):
self.verify = 0
also infinitive loop usually created like this
while True:
Always be careful using "global" is tricky and in most of cases you can do anything in simples and readable way, so I would recommend you remove all globals from this script, you can return params from functions, use mutable objects etc.

Related

I can't put "continue" command in a definition?

Let's say,
def sample():
if a==1:
print(a)
else:
continue
for i in language:
a=i
sample()
I want to use this function in a loop, but the continue command gives me an error because there is no loop. What can I do?
Return a boolean from the function and based on the return value make continue or not because continue must be within a loop
continue keyword in python is only available in for or while loops. Also block defined variables like a are not available on the global scope.
I don't know what you want to achieve but assuming your code, you want to extract a condition into a function, something like this:
def condition(a):
return a == 1
def sample(a):
print(a)
for i in language:
a=i
if condition(a):
sample(a)
else:
continue
There are several best-practice patterns of exactly how to do this, depending on your needs.
0. Factor your code better
Before doing any of the below, stop and ask yourself if you can just do this instead:
def sample(a):
print(a)
for i in language:
if i != 1:
continue
sample(i)
This is so much better:
it's clearer to the reader (everything you need to understand the loop's control flow is entirely local to the loop - it's right there in the loop, we don't have to look anywhere else farther away like a function definition to know when or why or how the loop will do the next thing),
it's cleaner (less boilerplate code than any of the solutions below),
it's more efficient, technically (not that this should matter until you measure a performance problem, but this might appeal to you; going into a function and coming back out of it, plus somehow telling the loop outside the function to continue - that's more work to achieve the same thing), and
it's simpler (objectively: there is less code complected together - the loop behavior is no longer tied to the body of the sample function, for example).
But, if you must:
1. Add boolean return
The simplest change that works with your example is to return a boolean:
def sample(a):
if a==1:
print(a)
else:
return True
return False
for i in language:
if sample(i):
continue
However, don't just mindlessly always use True for continue - for each function, use the one that fits with the function. In fact, in well-factored code, the boolean return value will make sense without even knowing that you are using it in some loop to continue or not.
For example, if you have a function called check_if_valid, then the boolean return value just makes sense without any loops - it tells you if the input is valid - and at the same time, either of these loops is sensible depending on context:
for thing in thing_list:
if check_if_valid(thing):
continue
... # do something to fix the invalid things
for thing in thing_list:
if not check_if_valid(thing):
continue
... # do something only with valid things
2. Reuse existing return
If your function already returns something, or you can rethink your code so that returns make sense, then you can ask yourself: is there a good way to decide to continue based on that return value?
For example, let's say inside your sample function you were actually trying to do something like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
else:
continue
Well then you can rewrite it like this:
def sample(a):
record = select_from_database(a)
if record.status == 1:
print(record)
return record
for i in language:
record = sample(a)
if record.status != 1:
continue
Of course in this simple example, it's cleaner to just not have the sample function, but I am trusting that your sample function is justifiably more complex.
3. Special "continue" return
If no existing return value makes sense, or you don't want to couple the loop to the return value of your function, the next simplest pattern is to create and return a special unique "sentinel" object instance:
_continue = object()
def sample(a):
if a==1:
print(a)
else:
return _continue
for i in language:
result = sample(i):
if result = _continue:
continue
(If this is part of a module's API, which is something that you are saying if you name it like sample instead of like _sample, then I would name the sentinel value continue_ rather than _continue... But I also would not make something like this part of an API unless I absolutely had to.)
(If you're using a type checker and it complains about returning an object instance conflicting with your normal return value, you can make a Continue class and return an instance of that instead of an instance of object(). Then the type hinting for the function return value can be a type union between your normal return type and the Continue type. If you have multiple control flow constructs in your code that you want to smuggle across function call lines like this.)
4. Wrap return value (and "monads")
Sometimes, if the type union thing isn't good enough for some reason, you may want to create a wrapper object, and have it store either your original return value, or indicate control flow. I only mention this option for completeness, without examples, because I think the previous options are better most of the time in Python. But if you take the time to learn about "Option types" and "maybe monads", it's kinda like that.
(Also, notice that in all of my examples, I fixed your backdoor argument passing through a global variable to be an explicit clearly passed argument. This makes the code easier to understand, predict, and verify for correctness - you might not see that yet but keep an eye out for implicit state passing making code harder to follow and keep correct as you grow as a developer, read more code by others, and deal with bugs.)
It is because the scope of the function doesn't know we are in a loop. You have to put the continue keyword inside the loop
continue keyword cannot be used inside a function. It must be inside the loop. There is a similar question here. Maybe you can do something like the following.
language = [1,1,1,2,3]
a = 1
def sample():
if a == 1:
print(a)
return False
else:
return True
for i in language:
if sample():
continue
else:
a = i
OR something like this:
language = [1,1,1,2,3]
a = 1
def gen(base):
for item in base:
if a == 1:
yield a
else:
continue
for i in gen(language):
a = i
print(a)

In python3, how to explicitly access a variable that is outside the scope of the block but not in the scope of the external function?

example:
# Suppose id(i) == A
i = 10
if some_condition:
i = 11
# How to make sure this 'i' has an id == A instead of B?
# Because at this time my pycharm prompts me that the i above is not used.
And what should I do when I want to declare a local variable just with the same name without affecting the value of i above?
Or, is there a way to force only assignment without declaring variables in python3, then an exception thrown to prompt developer when the name doesn't exist?
I will be appreciated if anyone offers help.
i think, the best answer is change the variable. But , if u still want to use it. U can try this
Make some function
i = 10
def scope_test():
def do_local():
i = 11
do_local()
print(i)
print(i)
scope_test()
print(i)

How to define input variable in python?

Error message reads, that number is not defined in line 5:
if number < int(6):
Using Qpython on android.
looper = True
def start() :
names = ["Mari", "Muri", "Kari"]
number = input("Whoms name to you want to know?")
number = int(number)
if number < int(6):
print(names[number])
else:
print("There arent that many members")
while looper :
start()
First of all, 6 is already an integer. There's no reason to type-cast it as one.
Next, you call start() after your if statement. Python reads code top-down, so the first thing it reads is your function definition, and then your if statement. Given that start() needs to be called for number to be defined, number represents nothing and cannot be compared to 6.
Well besides how you need to call the function before using the variable, you also have a simple issue of global and local variables.
Number is a local variable in the start() function and can only be used within it.
If you want to use the number variable outside the function, you can use the 'global' keyword in front of it, which should allow you to use it externally.
For example:
def func ():
global var
var = 10
func ()
print (var)
outputs 10

Python use input to select local variable inside another function

All, I have this request but first I will explain what I'm trying to achieve. I coded a python script with many global variables but also many methods defined inside different modules (.py files).
The script sometimes moves to a method and inside this method I call another method defined in another module. The script is quite complex.
Most of my code is inside Try/Except so that every time an exception is triggered my code runs a method called "check_issue()" in which I print to console the traceback and then I ask myself if there's any variable's value I want to double check. Now, I read many stackoverflow useful pages in which users show how to use/select globals(), locals() and eval() to see current global variables and local variables.
What I would specifically need though is the ability to input inside method "check_issue()" the name of a variable that may be defined not as global and not inside the method check_issue() either.
Using classes is not a solution since I would need to change hundreds of lines of code.
These are the links I already read:
Viewing all defined variables
Calling variable defined inside one function from another function
How to get value of variable entered from user input?
This is a sample code that doesn't work:
a = 4
b = "apple"
def func_a():
c = "orange"
...
check_issue()
def check_issue():
print("Something went wrong")
var_to_review = input("Input name of var you want to review")
# I need to be able to enter "c" and print the its value "orange"
print(func_a.locals()[var_to_review ]) # this doesn't work
Could somebody suggest how to fix it?
Many thanks
When you call locals() inside check_issue(), you can only access to the locals of this function, which would be : ['var_to_review'].
You can add a parameter to the check_issue function and pass locals whenever you call it.
a = 4
b = "apple"
def func_a():
c = "orange"
check_issue(locals())
def check_issue(local_vars):
print("Something went wrong")
var_to_review = input("Input name of var you want to review")
print(local_vars[var_to_review])

How can I make 'uName' display the correct name that the user inputs after clarifying checks?

I am very new to Python, as you can probably tell from the code. To begin, I am trying to have the user input their name and store that in a global variable that I can access all throughout my code...preferably named uName.
What's happening is during the loop cycle, it asks the user 'Is this your name?' after they input the first response. If I hit type anything but 'yes' or 'Yes', it will re-ask them to input the name. BUT, when they finally hit 'Yes', the program prints the very first name they entered.
Also, any tips on code structure or wording is helpful...
game.py
from decisions import *
import decisions
global globalname
globalname = ''
def gameEngine(uName):
looper = 0
while looper == 0:
print ('You said your name is, ') + uName + ('...')
clarifier = raw_input('Is that correct?\n')
if clarifier == 'yes' or clarifier == 'Yes':
namePrinter(answer)
else:
decisions.userDecisions(username)
def namePrinter(uName):
print uName
gameEngine(answer)
decisions.py
username = ''
def userDecisions(inputs):
response = raw_input("Please enter your name...\n>>> ")
return response
answer = userDecisions(username)
The specific issue that you are encountering is that you are first running the contents of decisions.py though the import statement in game.py. Through that, you have set the variable "answer" to be equal to the first name that the user inputs.
Then you are calling the gameEngine function in game.py, supplying the "answer" variable from decisions.py as the argument, which is stored in "uName". Upon the user entering another name the name is not stored anywhere and is thrown out with the following line.
decisions.userDecisions(username)
You can assign the return of that statement to a variable such as "uName", and that will get you closer to what you want to do.
uName = decisions.userDecisions(username)
The next issue is that when you are printing out the name, you are printing out the variable "answer" as opposed to "uName". This is what is mainly causing the issue of the first name always being printed out.
namePrinter(answer)
This could be resolved by passing in the "uName" variable instead.
namePrinter(uName)
Also if you want the final chosen name to be stored in the global variable you can assign the final user chosen name to the gloabl variable after the user confirms that the nameis correct.
globalname = uName
However, you may want to be careful about a few parts of the structure of your code.
First, you may want to try not to use global variables. Instead you should be passing around the name though the functions which use it. If you have other player information that you need to access often, you can create a Player class and object to store that information in a single object which can be passed around into functions as needed.
Second, as the userDecisions function does not use its arguement "inputs", you can remove that arguement, as it isn't used.
Third, you may want to be careful about running code through import statements alone. Generally when you are importing a source file, you should be importing the functions, and not rely upon imports to directly run code. For example you can remove the non-function lines of decisions.py and simply run the following in game.py instead.
gameEngine(decisions.userDecisions())
I reccomend that you look up some resources on functions and passing arguement in Python, as they might be able to explain the underlying concepts a bit better.
You have screwed up with the variables and their scope. Read more about them here.
To give you a perspective regarding the scope of variables concisely, look at this code snippet:
# This is a global variable
a = 0
if a == 0:
# This is still a global variable
b = 1
def my_function(c):
# this is a local variable
d = 3
print(c)
print(d)
# Now we call the function, passing the value 7 as the first and only parameter
my_function(7)
# a and b still exist
print(a)
print(b)
# c and d don't exist anymore -- these statements will give us name errors!
print(c)
print(d)
Regarding your code, you may want to have a look at these issues:
The answer variable is not accessible in the game.py module.
So is the case with username variable in the decisions.userDecisions(username) call.
The decisions.userDecisions(username) call in the gameEngine(uName) method is not storing the response to any variable and hence the response will be lost.
You are declaring global variable globalname but not assigning any value to it (of course other than '').
P.S.: I was tempted to do your homework for you, but then probably this is good enough information for you to learn more. ;)

Categories

Resources