Python Development [Type Error] - python

I am a beginner and recently started python development.
The code i was working on:
import random
import textwrap
def show_message(dotted_line,width):
print(dotted_line)
print("\033[1m"+ "Attack of clones:" + "\033[0m")
message = (
"The war between humans and their arch enemies , Clones was in the offing. Obi-Wan, one of the brave Jedi on his way ,"
"he spotted a small isolted settlement .Tired and hoping to replenish his food stock , he decided to take a detour."
"As he approached the village, he saw five residence , there was no one to be seen around.He decided to enter" )
print(textwrap.fill(message, width = width))
def show_mission(dotted_line):
print("\033[1m"+ "Mission:" + "\033[0m")
print('\t Choose the hit where Obi wan can rest...')
print("\033[1m"+ "TIP:" + "\033[0m")
print("Be careful as there are Stormtroopers lurking around!")
print(dotted_line)
def occupy_huts():
global huts
huts = []
while len(huts) < 5:
random_choice = random.choice(occupants)
huts.append(random_choice)
def process_user_choice():
message = "\033[1m"+ "Choose the hut to enter (1-5) " + "\033[0m"
uc = input("\n" + message)
index = int(uc)
print("Revealing the occupants...")
message = ""
def reveal_occcupants(index,huts,dotted_line):
for i in range (len(huts)):
occupant_info = "<%d:%s>"%(i+1,huts[i])
if i + 1 == index:
occipant_info = "\033[1m"+ "" + "\033[0m"
message += occupant_info + " "
print("\t" + message)
print(dotted_line)
def enter_huts(index,huts,dotted_line):
print("\033[1m"+ "Entering Hut %d ..." %index + "\033[0m")
if huts[index - 1] == 'clones':
print("\033[1m"+ "There's Stormtrooper Here!!" + "\033[0m")
else:
print("\033[1m"+ "It's Safe here!" + "\033[0m")
print(dotted_line)
def run():
keep_playing = 'y'
global occupants
occupants = ['clones','friend','Jedi Hideout']
width = 70
dotted_line = '-' * width
show_message(dotted_line, width)
show_mission(dotted_line)
while keep_playing == 'y':
huts = occupy_huts()
index = process_user_choice()
reveal_occcupants(index,huts,dotted_line)
enter_huts(index,huts,dotted_line)
keep_playing = raw_input("Play Again?(y/n)")
if __name__ == '__main__':
run()
and the error is in body of
def reveal_occupants.
"TypeError: object of type 'NoneType' has no len()"
how this error can be overcome and please suggest an alternative approach too

Here :
while keep_playing == 'y':
huts = occupy_huts()
Your occupy_huts() function doesn't return anything (it populates a global variable huts but doesn't return it), so the after the huts = occupy_huts() statement huts is now None (the default function return value if you don't explicitely return something). Then you pass this (now None) huts variable to reveal_occupants() :
reveal_occcupants(index,huts,dotted_line)
The solution is simple: modify occupy_huts so instead of working on a global (which is almost always a very bad idea) and returning None, it works on a local variable and returns it:
def occupy_huts():
huts = []
while len(huts) < 5:
random_choice = random.choice(occupants)
huts.append(random_choice)
return huts
While we're at it, you are using a global for occupants too, which is brittle (occupy_huts() will break if called before this variable has been created), while you could just pass it as argument:
def occupy_huts(occupants):
huts = []
while len(huts) < 5:
random_choice = random.choice(occupants)
huts.append(random_choice)
return huts
and then in run():
def run():
keep_playing = 'y'
occupants = ['clones','friend','Jedi Hideout']
# ...
while keep_playing == 'y':
huts = occupy_huts(occupants)
The funny thing here is that you pass arguments for mundane stuffs that are mostly constants and have no impact on the program's logic (ie dotted_lines), but use globals for the important things - should really be the other way round (declare dotted_lines as a pseudo_constant at the start of your module and don't bother passing it to functions) ;)
Also, note that you have a similar issue with process_user_choice() here :
while keep_playing == 'y':
huts = occupy_huts()
index = process_user_choice()
since your process_user_choice() function doesn't return anything either. You should modify it so it returns its local variable index.

len() method accepts an object as parameter.
in your case, at line 43, huts may be None, so you can get an error.
you should insert if condition like below after line 42
if huts is None:
return

My guess is that "huts" is None-type, because occupy_huts() was never called. Or there is an issue with the scope of the "huts" variable -- this might be cleared up by declaring it as an empty set outside of the occupy_huts() function.
Also, you could take advantage of Python's syntax and change line 43 to "for hut in huts:". If you also need the index of the hut, try "for hut, i-hut in enumerate(huts):".

You method "reveal_occupants" receive empty value as huts. That means, that type of huts is None. That why you can't get len of this value.

Related

How can I call a function using an if statement and then print the value returned inside the if statement?

This part of my if statement calls the find_feed function and it it returns None, the if statement completes, however if it returns anything else, the else statement re-calls the function: news_feed = feedparser.parse(find_feed(user_input))
Instead of calling the function twice (because it takes a bit to complete), I'd like to call it once and if it doesn't return None, use the returned value in the else statement instead of calling the function again. Can I do that, and if so, how?
elif find_feed(user_input) is None:
print("No location found.")
else:
print("Pulling weather data from Environment Canada.")
news_feed = feedparser.parse(find_feed(user_input))
brief_current()
more_question = input("\n" + "Would you like more details? (y or n) ")
if more_question == "y":
detailed_current()
Since PEP 572 in Python 3.8 you can also combine if statement with assignment so you don't have to create the variable in advance:
elif (unparsed_news_feed := find_feed(user_input)) is None:
print("No location found.")
else:
print("Pulling weather data from Environment Canada.")
news_feed = feedparser.parse(unparsed_news_feed)
brief_current()
more_question = input("\n" + "Would you like more details? (y or n) ")
if more_question == "y":
detailed_current()
Although here I'd suggest swapping two branches and inverting is None to is not None so unparsed_news_feed is only used in its corresponding branch.
Store the return value in a variable, so you can reference it later. See here:
xy = find_feed(x)
# Assumes a pre existing if statement
elif xy is None:
print('no location')
else:
print("Pulling weather data from Environment Canada.")
news_feed = feedparser.parse(xy)
brief_current()
more_question = input("\n" + "Would you like more details? (y or n) ")
if more_question == "y":
detailed_current()
You need to save the result of the call to find_feed before you test its value:
else: # instead of the original elif find_feed(user_input) is None:
result = find_feed(user_input)
if result is None:
print("No location found.")
else:
print("Pulling weather data from Environment Canada.")
news_feed = feedparser.parse(result)
brief_current()
more_question = input("\n" + "Would you like more details? (y or n) ")
if more_question == "y":
detailed_current()

How to give variable values from a function to another function?

Im making a "game" for practice. Its a basic guess game, but i wanted to make the game only with functions. This is my problem (for ex.):
function 1:
variablaA
#some other code
function 2:
variableB
variableC = varibleA + variableB
#some other code
I have tried too goole about objects and classes but im not sure i understand what im doing right now.
import random
import sys
min = 1
max = 99
guessed_number = random.randint(min, max)
class functions:
def __init__(game, difficulty, lifes):
game.difficulty = difficulty
game.lifes = lifes
def GameDiff(hardness):
#Setting game difficulty
print "Select difficulty : \n 1; Easy \n 2; Medium \n 3; Hard \n"
difficulty = raw_input()
if difficulty == "1":
print "Its just the beginning"
lifes = 15
elif difficulty == "2":
lifes = 10
elif difficulty == "3":
lifes = 5
else:
print "This isn't an option try again"
GameDiff(hardness)
def core(basic):
#The core of the game
print "I guessed a number..."
player_number = int(raw_input("Whats the number I thinking of?"))
constant = 1
GameTime = 1
while GameTime == constant:
if player_number < guessed_number:
print "Your number is smaller than my guessed number"
print "Try to duplicate your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
elif player_number > guessed_number:
print "Your number is bigger than my guessed number"
print "Try to half your number (But maybe Im wrong)"
player_number = int(raw_input("Make your tip again\n"))
else:
GameTime = 0
print "You guessed it! Congratulations"
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
Function.main()
if you are defining function with parameters, you need to pass data(parameters) into a function when you call it
example:
def my_function(name):
print("my name is " + name)
my_function("Kevin")
in your case you define:
def GameDiff(hardness):
def core(basic):
which are expecting parameters
and when you are calling those funcitions, you are doing that on wrong way:
def main(self):
#The whole game only with functions
functions.GameDiff()
functions.core()
Function = functions()
you need to pass parameters
example:
functions.GameDiff(5)
functions.core(1)
Function = functions(1,5)
NOTE: good practice will be to use self instead of game
def __init__(self, difficulty, lifes):
self.difficulty = difficulty
self.lifes = lifes
they are just two different kinds of class elements:
Elements outside the init method are static elements; they belong
to the class. They're shared by all instances.
Elements inside the init method are elements of the
object (self); they don't belong to the class.Variables created inside init (and all other method functions) and prefaced with self. belong to the object instance.

Python: 'other_activity' is not defined

I want to print the other_activity if its not empty after taking input from user but this error, I know its pretty basic but not able to find the solution
print("What kind of activity is this?")
print '\n'.join(acti)
userInput = raw_input("\n""Client->")
r = re.compile(userInput)
if not filter(r.match, acti):
print("not valid activity")
else:
if (userInput == "Other"):
event_activity = raw_input("-> Please specify your activity\n""Client->")
other_activity = ("Other:" + event_activity)
else:
event_activity = userInput
if not other_activity:
print("Activity type: ", other_activity)
else:
print("Activity type: ", event_activity)
Define other_activity = None at the top of your code (There are cases in your code when other_activity is never assigned, and thus, never created. By adding this default assignment, you are making sure the variable will exist when checking its value)
At the end, you can use a ternary condition to print one variable or the other:
print('Activity type:', other_activity if other_activity else event_activity)

Python fill-in-the-blanks code

I am a programming beginner and I am trying to build a fill-in-the-blank quiz. I am almost finished but I am stuck on 2 problems I am not able to solve, whatever I do. I would really appreciate your help with this. Thank you for helping me with this!
If you try to run the code and play the game:
1) It prints the quiz according to the difficulty(easy-insane) and quiz you want to play(apple, bond and programming quiz) which is great but afterwards it prompts you to choose difficulty again (the player_level() function keeps going even though the player/user has already chosen the difficulty level. I don't really understand why it does it? The player_level() procedure seems perfectly okay and logical to me.
2) The errors:
a) local variable blanks_index referenced before assignment
b) global name list_of_answers is not defined.
I know that it is related to the initialize_game() function but I don't know how to change the code so it refers all the variables (blanks_index, answers_index, player_lives) correctly.
It could be solved by creating global variables(I guess) but that is not a good practice so I am trying to avoid it. Formerly, the whole function initialise_game() and play_game() were one function, but as there are over 25 lines of code in one function, it is not a good practice as it is long and messy and I know that I can separate it but I don't know how.
Here is the code:
"""3 diffferent quizzes : Apple quiz, James Bond quiz, Programming quiz"""
"""Quiz and answers about Apple"""
Apple_quiz = ("The most valuable company in terms of market cap in 2016 is, ___1___."
"It was founded in ___2___. Its flagship product is called ___3___."
"___1___ has many competitors, the biggest rival is ___4___,founded by"
" nobody but the richest man on the planet,___5___ ___6___.")
list_of_answers_Apple = ["Apple", "1976", "Iphone", "Microsoft", "Bill", "Gates"]
"""Quiz and answers about Bond"""
Bond_quiz = ("James Bond is agent ___1___. He serves his country,___2___ ___3___"
" against its enemies. His car of choice is usually ___4___ ___5___."
" His favorite drink is ___6___.")
list_of_answers_Bond = ["007", "United", "Kingdom", "Aston", "Martin", "Martini"]
"""Quiz and answers about programming basics"""
Programming_quiz = ("___1___ are created with the def keyword. ___1___ are also called ___2___"
" You specify the inputs a ___1___ take by adding ___3___ separated by commas"
" between the parentheses. ___3___ can be standard data types such as string, number"
" ,dictionary, tuple, and ___4___ or can be more complicated such as ___5___"
" and ___6___ functions.")
list_of_answers_Programming = ["Functions", "procedures", "arguments", "lists", "objects", "lambda"]
blank_space = ["___1___", "___2___", "___3___", "___4___", "___5___", "___6___]"]
#List of levels with corresponding lives/guesses that player can have
quiz_list = ["Apple", "Bond", "Programming"]
level_list = ["easy", "medium", "hard", "superhard", "insane"]
lives_easy = 5
lives_medium = 4
lives_hard = 3
lives_superhard = 2
lives_insane = 1
def choose_quiz():
""" Prompts player to pick a type of quiz and loads the quiz """
#Input = player_quiz (raw input from player)
#Output = loaded quiz, player chose
while True:
player_quiz = raw_input("Please, select a quiz you want to play: "
"(Apple, Bond or Programming): ")
if player_quiz == "Apple":
return Apple_quiz
elif player_quiz == "Bond":
return Bond_quiz
elif player_quiz == "Programming":
return Programming_quiz
else:
print "We don't have such quiz, pick again!"
def answers_for_quiz():
""" Loads appropiate answers to the quiz that player has chosen"""
#Input = player quiz (raw input from player)
#Output = loaded quiz answers from the quiz player chose
player_quiz_pick = choose_quiz()
if player_quiz_pick == Apple_quiz:
return list_of_answers_Apple
elif player_quiz_pick == Bond_quiz:
return list_of_answers_Bond
elif player_quiz_pick == Programming_quiz:
return list_of_answers_Programming
def player_level():
""" Loads a difficulty that player chooses """
#Input = player_level_input (raw input of player choosing a difficulty)
#Output = corresponding number of lives:
#Easy = 5 lives, Medium = 4 lives
#Hard = 3 lives, Superhard = 2 lives
#Insane = 1 life
while True:
player_level_input = raw_input("Please type in a difficulty level: "
"(easy, medium, hard, superhard, insane): ")
if player_level_input == "easy":
return lives_easy #Easy = 5 lives
elif player_level_input == "medium":
return lives_medium #Medium = 4 lives
elif player_level_input == "hard":
return lives_hard #Hard = 3 lives
elif player_level_input == "superhard":
return lives_superhard #Superhard = 2 lives
elif player_level_input == "insane":
return lives_insane #Insane = 1 life
else:
print "We do not have such difficulty! Pick again!"
def correct_answer(player_answer, list_of_answers, answers_index):
""" Checks, whether the the answer from player matches with the answer list. """
#Input: player_answer (raw input that player enters in order to fill in the blank)
#Output: "Right answer!" or "Wrong! Try again!" this output will be later used in the game
if player_answer == list_of_answers[answers_index]:
return "Right answer!"
return "Wrong! Try again!"
def initialize_game():
"""Functions that sets up a game so we can play it """
player_quiz_pick, player_level_pick, list_of_answers = choose_quiz(), player_level(), answers_for_quiz()
print player_quiz_pick
print "\nYou will get maximum " + str(player_level_pick) + " guesses for this game. Good luck.\n"
blanks_index, answers_index, player_lives = 0, 0, 0
#for elements in blank_space:
while blanks_index < len(blank_space):
player_answer = raw_input("Please type in your answer for " + blank_space[blanks_index] + ": ")
if correct_answer(player_answer,list_of_answers,answers_index) == "Right answer!":
print "Correct answer! Keep going!\n"
player_quiz_pick = player_quiz_pick.replace(blank_space[blanks_index],player_answer)
answers_index += 1
blanks_index += 1
print player_quiz_pick
if blanks_index == len(blank_space):
print "Congratulations! You nailed it! You are the winner!"
else:
player_level_pick -= 1
if player_level_pick == 0:
print "Game over! Maybe next time!"
break
else:
print "One life less, that sucks! Have another shot!"
print "You have " + str(player_level_pick) + " guesses left."
initialize_game()
Your main problem is that you keep calling the same functions over and over again and do not save the input into variables. Here are some tips about your code and questions:
You are not doing anything with your player_level() method call, so the player doesn't actually chooses a level in a way that affects the game. You should change the function call, so the returned value will be stored.
//the call to the method:
player_level_pick = player_level()
Afterwards, you keep calling the player_level() method, and not using the actual answer that the user supplied. Change all player_level() appearences to player_level_pick - the variable you use to save the answer (as I showed above). Same goes to all other unneeded function calls such as choose_level().
You should initialize number_of_guesses, player_lives, list_of_answers, and other vars to a matching value to player_level_pick as well, so it will hold the right value according to the level. Likewise, you should change this line:
# the line that checks if game is over
# change from:
if number_of_guesses == player_lives:
# to :
if number_of_guesses == 0:
In order to return multiple values, you have to use tuples. Using multiple return statements one after the other does not work anywhere.
so, instead of:
return list_of_answers
return number_of_guesses
return blanks_index
return answers_index
return player_lives
you should use tuples, and unpack them properly:
# the return statement:
return (list_of_answers, number_of_guesses, blanks_index, answers_index, player_lives)
# and the unpacking in the calling function:
list_of_answers, number_of_guesses, blanks_index, answers_index, player_lives = initialize_game()
this way, all of the returned values go into the wanted variables in the calling function. this way, you need to call the initialize_game() from play_game(). it will be the efficient way for you.
Just saying it again, as I said in the end of (4) - you should unit initialize_game() and play_game() into a single function (because a lot of data is the same needed data), or just call initialize_game() from play_game().
Better practice then using this recursivly: return choose_level(), you should use a while True: loop, and just brake when you get a proper answer.

Append Python returns instead of overwriting

I'm teaching myself Python and writing a simple GPA calculator. I have very little programming experience prior other than a college Java course, so bear with my code.
The premise is, the code will ask if you want to add a course to the list. If you do, it runs a function asking you the class name. Every time you add a class it'll ask if you want to add another. If you don't, it'll spit out a list of the classes you've added and then ask you to enter in the grades. I didn't get the grading part done yet. I don't think that will be too hard.
The problem is you can add a bunch of classes and it will only spit out the last one you entered. I'm assuming the issue is in askAgain(): classList = addClasses() because it keeps overwriting, but I'm not sure how to avoid a global variable (since they're bad?) and still keep this from overwriting itself. I seem to draw a blank when trying to figure out how to call something once to intialize it and not run it again. I've also read that conditional variables are bad, so I'm not sure what's best practice here. thanks
def main():
askAgain()
return 0
def askAgain():
while True:
addOrNot = raw_input("Add a class? [y/n]: ")
if addOrNot == "Y" or addOrNot == "y":
classList = addClasses() #This is probably where my issue is.
else:
try:
editClassGradeSelection = mainMenu(classList)
addGrades(editClassGradeSelection, classList)
except:
print("Hey you didn't add any classes yet.")
def addClasses():
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classList.append(raw_input("Add class to the list: "))
return classList
def mainMenu(classList):
print("Here are the classes you've added: ")
counter = 0
for classes in classList:
print((str(counter+1)) + ". " + (str(classList[counter])) + "\n")
counter = counter + 1
while True:
editGrade = raw_input("Enter the number for the class grade to edit: ")
if int(editGrade) > len(classList) or int(editGrade) < 1:
print("Enter a proper number in the range listed.")
else:
break
return editGrade
def addGrades(editClassGradeSelection, classList):
print("debug stuff for now: ")
print((str(editClassGradeSelection)))
print((str(classList[:])))
if __name__ == '__main__':
main()
Although this snippet makes sure classlist is defined:
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classlist is a local variable, hence everytime you run that function, classlist will be [], which probably explains why you can't ever display more than one. The classlist you assign it to gets reassigned to the one element of classlist (addClasses scope) every time this line is called:
classList = addClasses() #This is probably where my issue is.

Categories

Resources