why are both if and else statement getting executed {python} - python

i have mentioned in store class method search to return None if the for loop end and still no return and in main i have written only if its a none then print nothing but it still prints "nothing"
i don't think there is any indentation as pointed out in questions of similar type
class book:
def __init__(self,_id,name,tech,price,auth):
self._id=_id
self.name=name
self.tech=tech
self.price=price
self.auth=auth
def _print(self):
print(self._id)
print(self.name)
print(self.tech)
print(self.price)
print(self.auth)
class store:
def __init__(self,bookdb,name='abc'):
self.bookdb=bookdb
self.name=name
def search(self,b_name,book_list):
for i in book_list:
if i.name==b_name:
return i._print()
else:
return None
def discount(self,tech,book_list):
amt=0
for i in book_list:
if i.tech==tech:
amt+=i.price
return amt*(0.9)
if __name__=="__main__":
t = int(input())
b_list=[]
bookdb=dict()
for i in range(t):
_id=int(input())
name=str(input())
tech=str(input())
price=int(input())
auth=str(input())
b_list.append(book(_id,name,tech,price,auth))
bookdb[i]=book(_id,name,tech,price,auth)
title=str(input())
tech=str(input())
store_i=store(bookdb)
if store_i.search(title,b_list)== None:
print('nothing')
else:
store_i.search(title,b_list)
if store_i.discount(tech,b_list)== 0:
print('0.0')
else:
print(store_i.discount(tech,b_list))
**Input**
3
1
TIC
CPP
300
Online
2
CR
JAVA
500
BSwamy
3
BR
JAVA
700
RAJA
TIC
JAVA
Output
1
TIC
CPP
300
Online
nothing
1080.0
output required
1
TIC
CPP
300
Online
1080.0
P.S. bookdb dic doesnt have any use here

The _print() method in class book has no return statement, so python will implicitly return None. Then in the search function, when you do return i._print(), it returns None as well, which is why you see the "nothing" output.
Since you're going to test the result, you might as well make search() return a boolean, here's a suggested edit:
def search(self,b_name,book_list):
for i in book_list:
if i.name==b_name:
i._print()
return True
else:
return False

You have a number of things wrong with your code.
First, if you are going to prompt input from the user, you should provide a message along with the prompt. Something like:
...
name=str(input("Enter Book Name: "))
...
Second, Python is very sensitive to the (visual) structure of your code (i.e. indentation levels). So for example, the "else" to your "if"s must always sit at the same indentation level.
def search(self,b_name,book_list):
for i in book_list:
if i.name==b_name:
return i._print()
else:
return None
Third, looking at this it's obviously not what you want. The return statement must come after the for loop
Fourth, returning i._print() isn't going to return i unless the _print function returns i as its last statement.
With these remarks, you should try
def search(self,b_name,book_list):
for i in book_list:
if i.name==b_name:
i._print()
return i
return None
Also, in general
Try giving your variable names that are descriptive. It was difficult to read and understand your code without using a debugger. You should be able to read it and understand as much as possible what it is doing. So variables like t or unobvious abbreviations should be avoided.
This goes along with prompting the user. If you are going to print things to the console, provide some text to explain what the user is reading. Something like:
...
print("Book Name: ", self.name)
...
There is more (Single Responsibility Principle,...), but this is a "okay" start. And you will learn more as you are moving forward.

Related

Switch Implementation of Object calling function in python

I am trying to implement the switch in Dictionary in Python. But when I call the method
chooices.get(x, "Ther is no program") It call all the Function in the statment rather than calling x function.
I have read this implementation
Replacements for switch statement in Python?
but it was not helpful in my case as my function has print statement
Main file contain the code
from Day1.Day1 import Day1
from Day2.TipCalculator import TipCalculator
def choose():
print("Choose From the following Program:\n")
day1 = Day1()
day1.day1()
day2 = TipCalculator()
day2.day2()
x = int(input());
chooices={
1: day1.program1(),
2: day2.program1(),
}
chooices.get(x, "Ther is no program")
choose()
Day1 Class contain code
class Day1:
def day1(self):
print('1. Band name Generator\n')
def program1(self):
print('Welcome to Band Name Generator.\n')
cityName=input('What\'s is the name of city you grew up?\n')
petName = input('What\'s your pet\'s name?\n')
print('Your Band Name could be : '+cityName+" "+petName)
Class Tip Calculator Code
class TipCalculator:
def day2(self):
print("2. Tip Calculator For Bill.\n")
def program1(self):
print('Welcome to tip calculator.\n')
I just need the implementation Of switch statement which call Requested Program just like switch. I know Its possible through If-else but Dictionary mapping seems too be good alternative of switch
Overview: the interpretor creates a closure for the variables that the child function uses that are non local. In this example the child variable, value is 22 and stored in the closure cell.
def parent(arg_1, arg_2):
value=22
my_dict = {'chocolate':'yummy'}
def child():
print(2*value)
print(my['chocolate'])
print(arg_1 + arg_2)
return child
new_function=parent(3,4)
print(cell.cell_contents for cell in new_function.__closure__])
If you don't have a lot of variants, the if/elif/else statements can be streamlined using a helper function for the switch. This is only syntactic candy but it may be sufficient for small value sets.
def switch(v): yield lambda *c: v in c
Example usage:
x = int(input())
for case in switch(x):
if case(1): day1.program1()
elif case(2): day2.program1()
else: print("there is no program")
supporting multiple values for the same method call:
x = int(input())
for case in switch(x):
if case(1,5): day1.program1()
elif case(2,3,4): day2.program1()
else: print("there is no program")
you can also use it in a more C-like style
x = int(input())
for case in switch(x):
if case(1,5):
day1.program1()
break
if case(2,3,4):
day2.program1()
break
else:
print("there is no program")
If you have python 3.10 or higher, a proper switch analogue was implmemented called "match" which should work quite well in replacing any nested if statments the other answers may have.
If you dont have 3.10, and you are okay with a pretty hacky solution, mine uses the ideas from withhacks (specifically from AnonymousBlocksInPython). I have recently created my own version of a switch statment in python that acts more like how i am used to in C#. You can expand this as much as you want, way past single line arguments or assignments.
It uses context managers so that you can treat each case as its own code block with indentation and all. It will never enter the cases if the case value does not match the switch value so for code that is extremely system taxing, you can be sure it is not running code that does not need to be.
import sys
class CaseReturn(Exception):pass
class Case:
def __init__(self, caseVal): self._caseVal_ = caseVal
def _trace_(self,frame,event,arg): raise CaseReturn
def __enter__(self):
if self._caseVal_ == Switch._singleton_._switch_: return
sys.settrace(lambda *args, **keys: None)
sys._getframe(1).f_trace= self._trace_
def __exit__(self,ExType,ExVal,ExTrace):
if ExType is None: raise CaseReturn
return ExType is CaseReturn
class Switch:
_singleton_:'Switch' = None
def __init__(self, switchVal,Default=None): self._switch_ = switchVal
def __enter__(self):Switch._singleton_ = self
def __exit__(self,ExType,ExVal,ExTrace):
Switch._singleton_ = None
return ExType is CaseReturn
with Switch(2):
with Case(1):
print('This should not make it')
with Case(2):
print('I made it')
with Case(3):
print('This should never be called')
You can easily extend this out to check multiple cases by just changing the caseVal to a list and doing if Switch._singleton_._switch_ in self._caseVal_:
One caveat is, you cannot make the Case statments one-liners like:
Case(0): print('I am one line')
That will not work and end up calling the code in that case no matter what.
I hope this is useful to you or anyone who is searching for custom Switch statments!

Baffling result (to me) using Decorator in Python 3

I don't even know how to word this question correctly (so I don't know if this topic's been discussed before or how to query it).
The code below returns something mind-boggling to me.
It's an exercise on Decorators. This one in particular was made to demonstrate how a Decorator could add HTML tags at the beginning and at the end of a string.
If I was to call a function that return a string using the decorator:
#AddTags('p','i','b')
the return values is say:
"p i b *Welcome Joe To my blog!*b i p"
How is it that a for loop returns a single one-line with all the values.
And how is it that if we don't use 'reversed' the result is backwards.
I'm starting to understand the concept of Decorators but this example is like pure magic...how does this works?
def AddTags(*tags):
def decorator(oldFunc):
def inside(*args, **kwargs):
code = oldFunc(*args, **kwargs)
for tag in reversed(tags):
code = "<{0}>{1}</{0}>".format(tag,code)
return code
return inside
return decorator
#AddTags("p","i","b")
def MyWebWelcome(name):
return "Welcome "+name+" To my blog!"
No magic, its just that code = "<{0}>{1}</{0}>".format(tag,code) keeps updating code with expanded versions of itself. By reversing the tags for the loop, you make sure that the rightmost tag is added first, then wrapped by the next, and so on til done. You can see the progression with a couple of print statements:
def AddTags(*tags):
def decorator(oldFunc):
def inside(*args, **kwargs):
code = oldFunc(*args, **kwargs)
for tag in reversed(tags):
print('code:', code)
code = "<{0}>{1}</{0}>".format(tag,code)
return code
return inside
return decorator
#AddTags("p","i","b")
def MyWebWelcome(name):
return "Welcome "+name+" To my blog!"
print('result:', MyWebWelcome('foo'))
which prints
code: Welcome foo To my blog!
code: <b>Welcome foo To my blog!</b>
code: <i><b>Welcome foo To my blog!</b></i>
result: <p><i><b>Welcome foo To my blog!</b></i></p>
And its nothing magical about decorators either. I could run just the loop itself:
>>> code = "foo"
>>> for tag in ("p", "i", "b"):
... print(code)
... code = "<{0}>{1}</{0}>".format(tag,code)
...
foo
<p>foo</p>
<i><p>foo</p></i>
>>> code
'<b><i><p>foo</p></i></b>'

Exercism Python Bob

I'm learning Python through Exercism.IO, I'm currently on the Bob problem where the object of the problem is as follows:
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
Bob answers 'Sure.' if you ask him a question.
He answers 'Whoa, chill out!' if you yell at him.
He says 'Fine. Be that way!' if you address him without actually saying
anything.
He answers 'Whatever.' to anything else.
So far I've passed a few tests and I'm stuck at a point where it's suppose to return whatever but all the characters are integers, so of course it's not working.
Here's where I'm failing:
def test_only_numbers(self):
self.assertEqual(
'Whatever.', bob.hey('1, 2, 3')
)
All the characters are integers and my test to see if they're yelling looks like this:
def is_yelling(self):
return self.sentence == self.sentence.upper()
Obviously the characters are the same when upper or lower case because they're numbers so the program thinks they're yelling. My question is how can I refactor this program to make it so that when the assertion is all numbers, it won't count it as yelling?
def hey(what):
sentence = SentenceThinker(what)
if sentence.is_silence():
return "Fine. Be that way!"
elif sentence.is_yelling():
return "Whoa, chill out!"
elif sentence.is_question():
return "Sure."
else:
return "Whatever."
class SentenceThinker(object):
def __init__(self, sentence):
self.sentence = sentence
def is_yelling(self):
return self.sentence == self.sentence.upper()
def is_question(self):
return self.sentence.endswith("?")
def is_silence(self):
return not self.sentence
consider using the built-in String method str.isupper()

Is there a way to detect if the user last entered text, or the program, in Python?

This may be impossible, but (without making a variable be set after the computer prints something) know if the computer has printed something last, or the user. e.g.
answer = raw_input("Say something.")
if "ok" in answer.lower():
print "Yay!"
if "poo" in answer.lower():
print "That's very childish"
if (computer hasn't printed anything already):
print "I'm not very talkative."
I have a lot of if branches to process the users input, but so loads of elifs and an else won't work. Thanks
As you already mentioned, you could just set a variable, but that doesn't look nice.
Alternatively you could collect your output:
answer = raw_input("Say something.")
output = []
if "ok" in answer.lower():
output.append("Yay!")
if "poo" in answer.lower():
output.append("That's very childish")
if not output:
output.append("I'm not very talkative.")
for o in output:
print o
Disclaimer: I don't do much Python coding, so I have no idea if that's pythonic enough.
You also define a inner function to handle the printing and setting of the variable:
def handler(answer):
handler.responded = False
def respond(output):
handler.responded = True
print output
if "ok" in answer:
respond("Yay!")
if not handler.responded:
respond("I'm not very talkative")
This uses the "nonlocal"-replacement as discussed in this question.
If you could use Python 3, this code could be a bit nicer by using nonlocal:
def handler(answer):
responded = False
def respond(output):
nonlocal responded
responded = True
print(output)
if "ok" in answer:
respond("Yay!")
if not responded:
respond("I'm not very talkative")

LPTHW ex. 45, how to return functions from a class in another module?

Trying to make my own RPG character generator for ex 45 in Zed Shaw's LPTHW. Part of the assignment is to make a new class for each 'room' of the program, like WelcomeScreen or ChooseMutations.
Here is the main program.
import rooms
class Program(object):
def __init__(self, start):
self.start = start
def run(self):
next_room_name = self.start
while True:
room = getattr(self, next_room_name)
next_room_name = room()
x = rooms.WelcomeRoom()
Program(x.hello_user())
And here is the rooms file its trying to pull stuff from.
class WelcomeRoom(object):
def __init__(self):
pass
def hello_user(self):
print '*' * 79
print '\n'
print '\t\tWelcome to the'
print '\t\tMetamorphosis Alpha Character & Random Encounter Generator'
print '\t\tProgrammed poorly by Raymond Weiss'
print '\n'
print '*' * 79
raw_input('Please press enter to continue')
return 'get_name'
def get_name(self):
name = raw_input('Hello, whats your name?',
'\n',
':> ')
But when I run the main program in python, it just logs out instead of returning the function get_name() from rooms. Output posted below.
Raymond-Weisss-MacBook-Pro:macgre Raylug$ python macgre.py
*******************************************************************************
Welcome to the
Metamorphosis Alpha Character & Random Encounter Generator
Programmed poorly by Raymond Weiss
*******************************************************************************
Please press enter to continue
Raymond-Weisss-MacBook-Pro:macgre Raylug$
I apologize in advance if my question title isn't exactly what im trying to ask, as a newbie its sometimes hard not knowing what exactly to ask.
You're returning a string, not a function (or function result). You probably want something like:
def hello_user(self):
return self.get_name
or
def hello_user(self):
return self.get_name()
Based on your program, I think you probably want the second one. The difference is that the first one returns the get_name function, whereas the second one returns the results of the get_name function.

Categories

Resources