Python if( ): vs if: - python

On Code Academy there is this course where in the example they show
def speak(message):
return message
if happy():
speak("I'm happy!")
elif sad():
speak("I'm sad.")
else:
speak("I don't know what I'm feeling.")
The above example will NOT be related to the rest of the code I show. That was just an example for the if statement. Now I was under the impression that when ever writing an if statement it had to end in an ():like the above example.
However when doing the assignments this does not work:
def shut_down(s):
if s == "yes"():
return "Shutting down"
elif s == "no"():
return "Shutdown aborted"
else:
return "Sorry"
However this works:
def shut_down(s):
if s == "yes":
return "Shutting down"
elif s == "no":
return "Shutdown aborted"
else:
return "Sorry"
My question is how come the () is not needed next to the "yes" and "no" but :is still needed. I thought whenever writing an if statement it will automatically have to end with ():. In that very first example, that's how it is shown. Do you understand my confusion.

In the example given, happy() and sad() are functions, and as such require parentheses. The if itself does not need parentheses at the end (and it shouldn't have them)

No, if has nothing to do with ()
happy is a function. happy() is a call to that function. So, if happy(): tests if the happy function returns true when called.
In other words, if happy(): speak("I'm happy!") is equivalent to
result_of_happy = happy()
if result_of_happy:
speak("I'm happy!")

As has been mentioned happy() / sad() are functions so they require (). In example two of your question you are comparing your value to the string "yes" because it is a string it does not require ().
Within an if statement you can use parentheses to make the code more readable and ensure certain operations are evaluated before others.
if (1+1)*2 == 4:
print 'here'
else:
print 'there'
Differs from:
if 1+1*2 == 4:
print 'here'
else:
print 'there'

Because string objects are not callable so what are you expecting then:
Then use lambda not that efficient tho:
def shut_down(s):
if (lambda: s == "yes")():
return "Shutting down"
elif (lambda: s == "no")():
return "Shutdown aborted"
else:
return "Sorry"

Related

python testing, how handle 'continue' statement loop

I'm learning how to use Python. I have a function with a conditional inside of it, if an invalid input is provided, it should restart the loop until a valid input is provided.
Unfortunately, this "restarting" behavior is causing an infinite loop within my tests (it circularly provides the wrong input). How can I pause, or break, or limit the output to one instance so I can test the returned string?
function:
def confirm_user_choice(choice: str):
while True:
user_response = input(f"\nYou chose '{choice}', is this correct? y/n ")
if user_response == "y":
return True
elif user_response == "n":
return False
else:
print("\nSelect either 'y' (yes) or 'n' (no)")
test:
import unittest
from unittest import mock
from src.utils.utils import addValues, confirm_user_choice
class TestConfirmUserChoice(unittest.TestCase):
def test_yes(self):
with mock.patch("builtins.input", return_value="y"):
result = confirm_user_choice("y")
self.assertEqual(result, True)
def test_no(self):
with mock.patch("builtins.input", return_value="n"):
result = confirm_user_choice("n")
self.assertEqual(result, False)
def test_invalid_input(self):
with mock.patch("builtins.input", return_value="apple"): <-- triggers func else case
result = confirm_user_choice("apple")
self.assertEqual(result, False)
You have a partial function: on a proper input, it will return a Boolean value, but it may not return at all, and you can't test that an infinite loop is indeed infinite.
To make it more testable, allow the function to take an optional iterable value that defaults to sys.stdin, allowing you to control what the function reads (and how long it will attempt to do so.)
def confirm_user_choice(choice: str, responses: Optional[Iterable[str]] = None):
if responses is None:
# An infinite stream of calls to input()
responses = iter(lambda: input(f"\nYou chose '{choice}', is this correct? y/n "), None)
for user_response in responses:
if user_response == "y":
return True
elif user_response == "n":
return False
else:
print("\nSelect either 'y' (yes) or 'n' (no)")
else:
# Note: cannot be raised from the default value of responses
raise ValueError("Unexpected end of responses")
Now your test can simply pass canned lists of responses, and either catch the expected ValueError, or look at the returned Boolean value.
import unittest
from src.utils.utils import addValues, confirm_user_choice
class TestConfirmUserChoice(unittest.TestCase):
def test_yes(self):
result = confirm_user_choice("y", ["y"])
self.assertTrue(result)
def test_eventual_yes(self):
result = confirm_user_choice("y", ["apple", "pear", "y"])
self.assertTrue(result)
def test_no(self):
result = confirm_user_choice("y", ["n"])
self.assertFalse(result)
def test_no_valid_input(self):
with self.assertRaises(ValueError):
result = confirm_user_choice(["apple"])
continue does nothing in your code
continue alows you to ignore a part of the code for some instance of the loop.
For example :
for i in range(2):
if i < 1:
continue
print(i)
Output :
1
For what you want to do, don't forget while is suppose to end when a condition is meet. Hence bypassing the condition using while True: and then using a if to exit your loop is a bit counter productive.
Just use the while condition :
user_response = ""
while user_response not in ["y", "n"]:
user_response = input("y/n ? ")
print(user_response)
Happy programming
I'm new to Python myself but in my understanding, unit tests investigate how function handle different inputs based on the function's return value or exceptions raised (if any).
Your function only exits when the user inputs either "y" or "n" or when an error is raised (for instance, if the user provides Crtl-Z). Your while loop does not break when a user inputs 'apple.' There is no return value for pytest (or the like) to inspect.
If you really want to test this, you'd have to rewrite your function so that's a little more modular. It would have to feature at least three different return values, including one that implies that the input was invalid.

Adding more than one line per case in a switch-case statement (python)

I'm new to programming and trying to understand how to use a switch-case statement in python. My problem is a syntax error that occurs when I try to use a statement that has more than one line per case. Is this possible? What am I missing? If it isn't possible, how is a switch-case statement useful?
This is the code I'm using to test this
drop = random.randint(1,3)
inventory = []
def randomDrop(i):
switcher ={
1:
"you got x"
inventory.append(x) #syntax error on this line
2:
"you got y",
inventory.append(y)
3:
"you got z",
inventory.append(z)
}
return switcher.get(i,"you got nothing")
randomDrop(drop)
Python doesn't support support switch case. The thing which you are using is dictionary. It is a key,value data structure.
Syntax of dict: {key1:value1, key2:value2}
but in place of value you are using multiple statement that's why the syntax error.
drop = random.randint(1,3)
inventory = []
def randomDrop(i):
switcher ={
1:
"you got x"
inventory.append(x) #multiple statement instead of value or reference
2:
"you got y",
inventory.append(y) #multiple statement instead of value or reference
3:
"you got z",
inventory.append(z) #multiple statement instead of value or reference
}
return switcher.get(i,"you got nothing")
randomDrop(drop)
Use if-else instead.
inventory = []
def randomDrop(i):
if i == 1:
inventory.append(x)
return 'you got x'
elif i == 2:
inventory.append(y)
return 'you got y'
elif i == 3:
inventory.append(z)
return 'you got z'
else:
return 'you got nothing'
drop = random.randint(1,3)
randomDrop(drop)
See:
https://docs.python.org/3/tutorial/controlflow.html
I believe you are trying to do this. Let me know if it helps.
inventory = []
def randomDrop(i):
if i == 1:
inventory.append(x)
print('you got x')
elif i == 2:
inventory.append(y)
print('you got y')
elif i == 3:
inventory.append(z)
print('you got z')
else:
print('you got nothing')
drop = random.randint(1,3)
randomDrop(drop)
Python doesn't support switch case. You will have to use if-elif-else insetad of switch case.
For a much more palatable and maintainable structure, you can use a helper function for the switch:
def switch(v): yield lambda *c: v in c
This will let you write the code in a C-like style:
for case in switch(i):
if case(1):
inventory.append(x)
return "you got x"
if case(2):
inventory.append(y)
return "you got y"
if case(3):
inventory.append(z)
return "you got z"
else:
return "you got nothing"

Logic and calling functions. Help me understand this code

I have some code that is basically a demo for how dict works. My problem is, I am not sure exactly when it is calling the process_order() function. It seems like the main loop (go_shopping) never calls it, but the script seems to work. The go_shopping function calls get_item, but that doesn't call process_order either. I am also having trouble with the line if not process_order(order, cart):. What does the if not part mean in this case? Is that where it is calling process_order? It doesn't seem like it from the print statements, other wise it should print 'if not' when you add an item to the cart dictionary object.
Am I on the right track or missing something simple?
Code:
#!/usr/bin/python3.5
def get_item():
print("[command] [item] (command is 'a' to add, 'd' to delete, 'q' to quit.)")
line = input()
command = line[:1]
item = line[2:]
return command, item
def add_to_cart(item, cart):
if not item in cart:
cart[item] = 0
cart[item] += 1
def delete_from_cart(item, cart):
if item in cart:
if cart[item] <= 0:
del cart[item]
else:
cart[item] -= 1
def process_order(order, cart):
command, item = order
if command == "a":
add_to_cart(item, cart)
print('added to cart')
elif command == "d" and item in cart:
delete_from_cart(item, cart)
elif command == "q":
return False
print ('end process_order func')
return True
def go_shopping():
cart = dict()
while True:
print ('start main loop')
order = get_item()
print ('exited process_order')
if not process_order(order, cart):
print ('if not')
break
print ('while loop end')
print (cart)
print ("Finished!")
go_shopping()
Thing is, I am not really sure of your problem. But you seem concerned with the moment when process_order method is called.
When you write
if not process_order(order, cart)
it must be seen as follows (just adding parentheses):
if (not process_order(order, cart))
So you're asking Python to do something if the condition not process_order(order, cart) is true. So, Python must know the boolean value of the expression not process_order(order, cart).
This expression is composed of a unary operator, not, and a non-elementary expression, process_order(order, cart). That latter expression needs to be evaluated, so Python has to run the process_order method.
Therefore, when you write if not process_order(order, cart), the process_order method is indeed executed.

Syntax error at second definition in Python

def specificChecker(someThing, checker):
if checker == None:
return someThing
elif checker == True:
return not someThing
else:
return None
def whatDoesTheCheckerSay(someThing):
if specificChecker(someThing) == someThing:
return 'The checker value was False on that one.'
elif specificChecker(someThing) == not someThing:
return 'The checker value was True on that one.'
elif specificChecker(someThing) == None:
return 'Something irregular happend. The checker value wasn\'t None or True.'
else:
return 'Something went really wrong. This doesn\'t even not work.'
reallySomeThing = input('Type in really some thing: ')
theChecker = input('Set the checker to something: ')
print(specificChecker(reallySomeThing, theChecker))
print(whatDoesTheCheckerSay(reallySomeThing)) # This can be made more efficient, right?
def one(someShit):
return someShit + ' AWWW YEAH!'
def two(someShit):
return one(someShit)
print(two(input('Type in some kind of stuff: ')))
I'm a self-taught beginner, so surely it's something awkwardly basic. I'm using the IDLE shell and have repeatedly gotten a syntax error at the second definition statement of my codes. Please help?
You cannot use the line:
elif specificChecker(someThing) == not someThing:
This must be written
elif specificChecker(someThing) != someThing:
to be valid Python.
This is also valid but is perhaps less readable:
elif (specificChecker(someThing)) == (not someThing):
After OP edit:
The new error is the mismatch in arguments (always 1) to a function that requires 2 arguments. You have to pass two arguments to specificChecker not one
Line 12: elif specificChecker(someThing) == not someThing:
If you want to check if some variable is not some variable, used is not for boolean or != for values and strings

Python: Getting an undefine variable error when trying to call a function?

I'm still pretty new to Python, but it seems I've run into a problem. I get an undefined error when trying to call another function that defines that variable.
def unpackCon():
unpackConfirm = input("Unpack contents?[Y/N] ")
def unpackConScript():
if unpackConfirm == "y":
print ("Unpack confirmed.")
elif unpackConfirm == "n":
print ("Unpack unconfirmed.")
else:
print ("Value %s is not valid.") % (unpackConfirm)
unpackCon()
unpackCon()
unpackConScript()
Knowing Python, it's probably got something to do with indentation and the sorts. At first I believed it was because I called the function without defining it first, but I switched around the orders a bunch of times with no result.
Appreciate an answer!
unpackConfirm is defined inside of unpackCon(), and is out of scope in the other function. You need to return the variable in order to access it.
try:
def unpackCon():
unpackConfirm = input("Unpack contents?[Y/N] ").lower()
return unpackConfirm
def unpackConScript():
unpackConfirm = unpackCon()
if unpackConfirm == "y":
print ("Unpack confirmed.")
elif unpackConfirm == "n":
print ("Unpack unconfirmed.")
else:
print ("Value %s is not valid.") % (unpackConfirm)
unpackCon()
unpackConScript()

Categories