**(Beginner question) It seems I built a house without including a door. As an example, say you have three def blocks:
def intro ( ):
blah
def middle ( )
def middle ( ):
blah
def end ( )
def end ( ):
blah
intro ( ) #calling function here to start prog causes infinite loop
Computer initializes all defs but then exits prog because nothing points back to start. How do you start? If I make def intro the last line in the prog, the thing gets stuck in an infinite loop.
Do not write def before a function call. Try this instead:
def intro():
print "intro"
middle()
def middle():
print "middle"
end()
def end():
print "end"
intro()
Related
I'm learning how to code using Codecademy and I am really stuck on a question, and would love to be pointed in the right direction!
The code for the most part works, I just cannot get it to respond to the .match_reply function correctly. The idea is that the chatbot should identify the regex in self.alienbabble and respond with the appropriate answer. However, it is bugging out with an infinite recursion of all the responses of that function.
# importing regex and random libraries
import re
import random
class AlienBot:
# potential negative responses
negative_responses = ("no", "nope", "nah", "naw", "not a chance", "sorry")
# keywords for exiting the conversation
exit_commands = ("quit", "pause", "exit", "goodbye", "bye", "later")
# random starter questions
random_questions = (
"Why are you here? ",
"Are there many humans like you? ",
"What do you consume for sustenance? ",
"Is there intelligent life on this planet? ",
"Does Earth have a leader? ",
"What planets have you visited? ",
"What technology do you have on this planet? "
)
def __init__(self):
self.alienbabble = {'describe_planet_intent': '.*\s*your planet.*','answer_why_intent': 'why\sare.*', 'cubed_intent': '.*cube.*(\d+)'}
# Define .greet() below:
def greet(self):
self.name = input("Hello. What is your name?")
will_help = input(f"Hi {self.name}, I'm Etcetera. I'm not from this planet. Will you help me learn about your planet? ")
if will_help in self.negative_responses:
print ("Ok, have a nice Earth day!")
return
self.chat()
# Define .make_exit() here:
def make_exit(self, reply):
for word in self.exit_commands:
if word in reply:
print ("Ok, have a nice Earth day!")
return True
# Define .chat() next:
def chat(self):
reply = input(random.choice(self.random_questions)).lower()
while not self.make_exit(reply):
reply = input(self.match_reply(reply))
# Define .match_reply() below:
def match_reply(self, reply):
for key, value in self.alienbabble.items():
intent = key
regex = value
#regex = 'describe_planet_intent'
#reply = input(random.choice(self.random_questions)).lower()
found_match = re.match(regex, reply)
if found_match and intent == 'describe_planet_intent':
return self.describe_planet_intent()
elif found_match and intent == 'answer_why_intent':
return self.answer_why_intent()
elif found_match and intent == 'cubed_intent':
return self.cubed_intent(found_match.groups()[0])
else:
return self.no_match_intent()
# Define .describe_planet_intent():
def describe_planet_intent(self):
responses = ("My planet is a utopia of diverse organisms and species. ", "I am from Opidipus, the capital of the Wayward Galaxies. ")
return random.choice(responses)
# Define .answer_why_intent():
def answer_why_intent(self):
responses = ("I come in peace. ", "I am here to collect data on your planet and its inhabitants. ", "I heard the coffee is good. ")
return random.choice(responses)
# Define .cubed_intent():
def cubed_intent(self, number):
number = int(number)
cubed_number = number * number * number
return (f"The cube of {number} is {cubed_number}. Isn't that cool? ")
# Define .no_match_intent():
def no_match_intent(self):
responses = ("Please tell me more. ", "Tell me more! ", "Why do you say that? ", "I see. Can you elaborate? ", "Interesting. Can you tell me more? ", "I see. How do you think? ", "Why? ", "How do you think I feel when you say that? ")
return random.choice(responses)
# Create an instance of AlienBot below:
my_bot = AlienBot()
my_bot.greet()
I feel like there is a really simple solution to this, I've only been coding for 1 week so this is really new to me, and I appreciate your help :)
The answer is indeed simple. Let's reduce your code to a minimally reproducible one:
def match_reply(self, reply):
for key, value in self.alienbabble.items():
# I omitted the 3 lines that were here - defining 'intent', 'regex_pattern' and 'regex' -
# since at this point they're yet not used
reply = input(self.match_reply(reply)) # oops! self.match_reply is called again!
As you can see, you recursively call self.match_reply without anything to stop it.
EDIT:
There are another 2 things you need to fix:
Let's change match_reply:
a. Let's give it the more appropriate name match_alien_response.
b. Let's make it do what it should: just match a reply. Thus, we don't need it to get another input from the user.
c. Let's make sure it iterates all the keys in alienbabble and doesn't return immediately.
d. We need to use re.findall to get all matches in a string
All these changes give us the following code:
def match_alien_response(self, userReply):
found = False
for intent, regPattern in self.alienbabble.items():
found_match = re.findall(regPattern, userReply)
if found_match and intent == 'describe_planet_intent':
return self.describe_planet_intent()
elif found_match and intent == 'answer_why_intent':
return self.answer_why_intent()
elif found_match and intent == 'cubed_intent':
return self.cubed_intent(found_match[0])
if not found:
return self.no_match_intent()
Inside no_match_intent, it should be responses = instead of responses:
Consider the following code:
def add_function(a, b):
c = str(a) + b
print "c is %s" % c
def add_int_function(c, d):
e = c + d
print "the vaule of e is %d" % e
if __name__ =="__main__":
add_function(59906, 'kugrt5')
add_int_function(1, 2)
It always shows me: "expected 2 blank lines ,found 1" in aadd_int_function, but not in the add_function.
When I add two spaces in front of the def add_int_function(c, d):
there is a error shows unindent does not match any outer indentation level
in the end of add_function:
Just add another line between your function definitions :
1 line :
2 lines:
This is a pretty common question within the python community. After the release of PEP 8, new formatting styles were accepted into python. One of them states that after the definition of a class or function there must be two lines separating them. As such:
def yadayada:
print("two lines between the functions")
def secondyadayada:
print("this is the proper formatting")
So, you should never do it like:
def yadayada:
print("two lines between the functions")
def secondyadayada:
print("this is the proper formatting")
Or else PyCharm will throw that error at you.
Further clarification on #kennet-celeste & #shreyshrey 's answers,
Each function or class defined requires 2 spaces above and 2 spaces below. Unless the function is the last item in the script, in which the expected format is one blank line as an End of File marker. So:
# some code followed by 2 blank spaces
def function1():
def function2():
def function3():
For people who wonders why it requires two blank lines
if you were to write in other languages it would be:
fun doSth() {
print()
}
fun doSth1() {
print()
}
but if you were to delete all the curly braces from the code you will see:
two blank lines between methods
fun doSth()
print()
#
#
fun doSth1()
print()
#
Totally new to Python OOP. I am trying to write a code to separate anagrams (https://en.wikipedia.org/wiki/Anagram) in a list. The original question from Leetcode is here (https://leetcode.com/problems/anagrams/) For example:
strs=["eat", "tea", "tan", "ate", "nat", "bat"]
It should return:
[['eat', 'tea','tan','ate','nat'], ['bat']]
I see some discussion codes like (https://leetcode.com/discuss/51190/1-line-ruby-python-for-updated-problem):
def groupAnagrams(self, strs):
groups = collections.defaultdict(list)
for s in strs:
groups[tuple(sorted(s))].append(s)
return map(sorted, groups.values())
Or (https://leetcode.com/discuss/83032/without-sorting-each-string-use-hash-instead-concise-python)
def groupAnagrams(self, strs):
dic = collections.defaultdict(list)
for str in strs:
dic[reduce(operator.mul, map(hash, str), 1)].append(str)
return map(sorted, dic.values())
The question is: how can I make this class/function runs to take the list "strs"
as an input and output the desired list?
groupAnagrams(self,list1)
NameError: name 'self' is not defined
Call class then we will use the method:
class A(object):
some_method = groupAnagrams
a = A()
print a.some_method(list1)
this will give us:
[['bat'], ['ate', 'eat', 'tea'], ['nat', 'tan']]
I have the following function defined:
def displayHand(hand):
"""
Displays the letters currently in the hand.
For example:
>>> displayHand({'a':1, 'x':2, 'l':3, 'e':1})
Should print out something like:
a x x l l l e
The order of the letters is unimportant.
hand: dictionary (string -> int)
"""
for letter in hand.keys():
for j in range(hand[letter]):
print letter, # print all on the same line
print '' # print an empty line
Now, I want to print the following:
Current hand: a b c
To do this, I try to do:
print "Current hand: ", displayHand({'a':1, 'b':1, 'c':1})
And I get:
Current hand: a b c
None
I know that None is printed cause I am calling the print function on the displayHand(hand) function, which doesn't return anything.
Is there any way to get rid of that "None" without modifying displayHand(hand)?
if you want to use your function in a print statement, it should return a string and not print something itself (and return None) - as you would do in a __str__ method of a class. something like:
def displayHand(hand):
ret = ''
for letter in hand.keys():
for j in range(hand[letter]):
ret += '{} '.format(letter) # print all on the same line
# ret += '\n'
return ret
or even
def displayHand(hand):
return ''.join(n*'{} '.format(k) for k,n in hand.items() )
When you trail a print with a ,, the next print will appear on the same line, so you should just call the two things on separate lines, as in:
def printStuff():
print "Current hand: ",
displayHand({'a':1, 'b':1, 'c':1})
Of course you could just adapt this and create a method like:
def printCurrentHand(hand):
print "Current hand: ",
displayHand(hand)
The only way to do this (or I believe the only way to do this) is to use return instead of print in your displayhand() function. Sorry if I didn't answer your question.
Your function 'displayHand' does not have to print the output,
it has to return a string.
def displayHand(hand):
mystring=''
for letter in hand.keys():
for j in range(hand[letter]):
mystring+= letter # concatenate all on the same line
return mystring
BUT, you have to check the '.keys' command help as the order of the input (a/b/c) may not be respected
def check_answer(self, currentscore):
self.user_entry = self.user_entry.get_text()
if self.user_entry == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
When i run it and i put text a second time is says File "C:\Python27\guessing.py", line 16, in check_answer
self.user_entry = self.user_entry.get_text()
AttributeError: 'str' object has no attribute 'get_text'
Could someone explain it to me. Why it to me why it only works once. and also why doesn't the program execute the if statement. It only says wrong.
self.books = 'hello'
You overwrite the variable holding the reference to the text box with its contents. So when check_answer runs for the first time, self.user_entry is your text box, and you can call its method get_text() to retrieve the text entered by the user. Unfortunately, you assign this text to the same variable (self.user_entry =) - so you loose the reference to the text box. After the first call, self.user_entry is a string (instance of str class) retrieved at the first call.
Use a different variable name, like this:
def check_answer(self, currentscore):
self.user_entry_text = self.user_entry.get_text()
if self.user_entry_text == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
Also, possibly it doesn't have to be class's field, so you can also skip the self. part. In such case you could use the same name (user_entry), but for sake of readability it's better to call a variable with a name that says precisely what the variable holds:
user_entry_text = self.user_entry.get_text()
if user_entry_text == self.books: