Python Beginner Programming - python

I am still working on the same encryption program before and I am currently stuck.
choice = ""
def program (str,my_fn):
global i
i=0
while i<len(str):
my_fn
i += 1
def encrypt(my_result):
message.append(ord(answer[i]))
while choice != "Exit":
choice = input("Do you want to Encrypt, Decrypt, or Exit?\n")
if choice == "Encrypt":
answer = input("What would you like to encrypt:\n")
message = []
program(answer,encrypt(message))
print (answer)
print (message)
So the first part of the program is simply asking the user if they wish to Encrypt, Decrypt, or Exit the program, this part works perfectly fine. However, my issue is with the functions. Function "program" is intended to serve as a repeater for the inner function for every single letter in the string. However, when I try to run the program, it continues to tell me that "i" isn't defined for the "encrypt" function and does nothing. I am certain I set "i" as a global variable so why isn't this working. In case you are wondering why I chose to make two functions, it is because I will later have to use function "program" multiple time and for this specific assignment I am required to use functions and abstractions. Thanks!

Add one line after your first line
choice = ""
i = 0
The keyword global means you declare an access to a global name.
Also, using a global variable is almost never a good idea. You may want to find another way to design your function.

The line program(answer,encrypt(message)) doesn't do what you want it to do. Rather than passing the function encrypt and its argument message to program (which can call it later), it calls the function immediately. It would pass the return value to program instead, but since encrypt(message) doesn't work without i defined, you get an exception instead.
There are a few ways you could fix this. By far the best approach is to not use global variables in your functions, and instead always pass the objects you care about as arguments or return values.
For instance, you could pass a function that encrypts a single letter to another function that repeatedly applies the first one to a string (this would be very much like the builtin map function):
def my_map(function, string):
result = []
for character in string:
result.append(function(character))
return result
def my_encryption_func(character):
return ord(character)
If you really want to stick with your current architecture, you could make it work by using functools.partial to bind the answer argument to your encrypt function, and then call the partial object in program:
from functools import partial
def program (str,my_fn):
global i
i=0
while i<len(str):
my_fn() # call the passed "function"
i += 1
def encrypt(my_result):
message.append(ord(answer[i]))
choice = ""
while choice != "Exit":
choice = input("Do you want to Encrypt, Decrypt, or Exit?\n")
if choice == "Encrypt":
answer = input("What would you like to encrypt:\n")
message = []
program(answer, partial(encrypt, message)) # pass a partial object here!
print (answer)
print (message)

Related

NameError: name 'uinput' is not defined error in Python

I'm trying to make a simple CLI app for todo-lists. What's happening here? Is it because I'm referring to a variable that's inside a function?
I've tried putting "global" behind uinput, but that said that the "=" was not valid syntax or something along those lines. Not quite sure why, I've also tried looking around for a while on google and couldn't find anything, sorry if it is obvious.
userlist = []
def maininput():
uinput = input("What would you like to add to your list?")
userlist.append(uinput)
for i in userlist:
print(userlist)
break
while uinput != "exit":
maininput()
What I would like that happened was that "uinput" could be recognized to do the while statement
You should declare your uinput in your function globally in a such way:
global uinput
uinput = input("...")
In global scope(before declraring a function) you should specify a value for uinput
uinput = input("...")
Intead of ... you should fill in your input prompt
Use a while True loop to break your list inside maininput, instead of using a global like below. Also you can print the list directly using print(userlist), instead of a for loop
userlist = []
def maininput():
while True:
uinput = input("What would you like to add to your list? Type exit to stop>>")
#Exit the loop when you type exit
if uinput == "exit":
break
#Else append to list and print it
userlist.append(uinput)
print(userlist)
#Call the main function
maininput()
The outputs will look like
What would you like to add to your list? Type exit to stop>>a
['a']
What would you like to add to your list? Type exit to stop>>b
['a', 'b']
What would you like to add to your list? Type exit to stop>>c
['a', 'b', 'c']
What would you like to add to your list? Type exit to stop>>d
['a', 'b', 'c', 'd']
What would you like to add to your list? Type exit to stop>>exit
Short answer: yes, it's because you are referring to a name that's defined inside a function. You are now aware of a concept called "scoping."
Inside any Python function, names are resolved by looking in three places in order:
The function call's local namespace, created when the function
is called and destroyed when it returns or otherwise exits;
The module's global namespace, which is where top-level classes and
functions are defined;
The built-in namespace, which contains Python's pre-defined values like
None, Exception - all the names that are a part of the Python language.
Outside a function, statements (sometimes referred to as top-level statements) the local and global namespaces are the same.
When the interpreter compiles a function call, any names that are bound (by assigning them a value, or defining a nested class or function) are assumed to be local to that call. This is why the top-level statements couldn't reference uinput.
Other answers have given you some insight into a better looping structure. I'd encourage you, as your skill level grows, to investigate modules like pickle and shelve or even dbm, which will let your to-do lists stay alive between program runs.
You place the last input word in userlist, and it's easy to access userlist contents from the main loop because ① userlist is initialized in the main ② when the function search for a list to which append the user's input it finds userlist in the outer scope and ③ userlist is a mutable object, whose changes are visible from every point in its scope.
userlist = []
def ask():
new = input('...')
userlist.append(new)
if new == 'exit' : return
print('List contains', ', '.join(s for s in userlist))
while userlist[-1:] != ['exit']:
ask()
(we write the test like this: userlist[-1:] != ['exit'] because at the first pass userlist is empty and indexing it, rather than extracting a slice, would raise an error).
Of course this is BAD PRACTICE because we introduce a strong coupling between the main and the function, it's much better to pass explicitly the list in the argument list:
userlist = []
def update_list(a_list):
new = input('...')
a_list.append(new)
if new == 'exit' : return
print('List contains', ', '.join(s for s in a_list))
while userlist[-1:] != ['exit']:
update_list(userlist)

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

Where to create avoid global variables when creating objects in Python

I have written a simple menu function that i want to call from my main_program() function. The code also includes a class called Writing which I'm trying to make an object of inside the main_program(). The reason for this is that I've heard that it's preferable to avoid global variables. However this doesn't work and I get the answer: NameError: name 'writing_obj' is not defined
When I create the object outside the main_program() everything works fine so I guess is that I have to return my object writing_obj from the main_function() somehow?
Here is the code I wrote:
class Writing:
def writing_something(self):
print("I'm learning Python ")
def menu():
while True:
val = int(input("1. Write a sentence 2. Quit "))
if val == 1:
writing_obj.writing_something()
elif val == 2:
print("The program shuts down. See ya! ")
break
else:
print("Sorry, I din't get that! ")
continue
def main_program():
writing_obj = Writing()
menu()
main_program()
writing_obj is defined within the main_program() function and is not declared to be global. I would suggest using function arguments:
...
def menu(writing_obj):
...
def main_program():
writing_obj = Writing()
menu(writing_obj)
You could instead put global writing at the beginning of the main_program() definition, but as you said, global variables are not recommended.

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. ;)

Calling function from input variable

def function1(arguments):
print("Function 1",arguments)
def function2(arguments):
print("Function 2",arguments)
userInput = input()
Is it possible for the user to enter a function and arguments and for said function to run. eg the user enters function2("Hello World")
Though you can always use eval to make this work but for reasons eval is evil, it is better to use a dictionary call back mechanism, notably
You can create a dictionary to bind the function with the names and call them with appropriate parameters
call_backs = {'function1': function1, 'function2': function2}
assuming you provide an input as follows function2, "Hello World",
You first need to split the data userInput = userInput .split(',') and pass it onto the callback function via the dictionary
call_backs[userInput[0]](userInput[1])

Categories

Resources