below is my an example of what i am trying to do in my code...
def func():
x = int (input ('enter x: '))
return x
def func2():
y = int (input( 'enter y: '))
return y
def func3(x,y):
print(randomint(x,y))
def main():
func()
func2()
func3()
main()
What i am wondering is, why cant i use the x and y variables that i have defined via input and returned at the end of my functions? When this program tries to run it says the functions are missing required arguments. Silly i know, i am new to python.
furthermore, how can i use variable in one function i am creating, that were defined within another separate function? thanks!
You stated that you know how to indent so I'm not going to discuss that, the problem at hand is that you will need to catch the return value from func and func2 after they are caught.
You can do so like this:
def func():
x = int (input ('enter x: '))
return x
def func2():
y = int (input( 'enter y: '))
return y
def func3(x,y): # there's two positional value so you will need to pass two values to it when calling
print(randomint(x,y))
def main():
x = func() # catch the x
y = func2() # catch the y
func3(x,y) # pass along x and y which acts as the two positional values
# if you're lazy, you can directly do:
# func3(func(), func2()) which passes the return values directly to func3
main()
Another method is to use the global statement, but that isn't the best way for your case.
Just a hint: if you are using the random module, the random integer is called by: random.randint(x,y)
Your variables only live within the functions, there is no way for func3 to get x and y, but you have defined x and y as parameters. So far you're just not passing them in. The following should do.
def func():
x = int (input ('enter x: '))
return x
def func2():
y = int (input( 'enter y: '))
return y
def func3(x,y):
print(randomint(x,y))
def main():
x_val = func()
y_val = func2()
func3(x_val, y_val)
main()
Or just like this, if you don't want to use variables.
Just remember, same name doesn't mean it's the same variable. The scope can be different (method, function, elsewhere), and the name makes the variable unique ("the same") withhin the same scope. That is similar across all higher programming languages, but also, scopes can intersect, and in different ways. So that reuse example above, might, for example work in JavaScript.
This is probably closest to what you attempted to achieve:
def inX():
return int (input ('enter x: '))
def inY():
return int (input( 'enter y: '))
def PrintRand(x,y):
print(randomint(x,y))
def main():
PrintRand(InX(),InY()) # is probably closest to what you attempted to do.
main()
note that those slight renames do not have an effect other than understanding the code, but good names of methods telling what they actually do, are very important. You read the code many more times. You write it once.
Related
I'm new to python and I want to convert a loop "for" into a function. My loop I created enables me to multiply all the number of a list and print the result. This is my loop:
a=[1,2,3,4,9]
y=1
for x in a:
y=y*x
print(y)
As you can see I tried it with a certain list and I always put y=1 to start my loop and it works very well but when I want to create a function of that loop it fails, so far I tried that:
a=[]
y=1
def produit_entier(a):
for x in a:
y=y*x
return y
a=[1,2,3,4,9]
y=1
print(produit_entier(a))
As you can see I tried it with a certain list and when I run my code it tells me "local variable 'y' referenced before assignment", and when I remove the "y=1" line and put it right after the "for x in a:" this message disappear but the result is always 1.
So I'm lost here, my function is almost exactly the same as my loop, but my loop works very well and not my function, so I would really appreciate help here. Thx in advance
The y needs to be declared inside the function, since it is used by the function.
def produit_entier(a):
y = 1
for x in a:
y=y*x
return y
Karim!
First of all, there is a problem with the return statement. You placed it the wrong way, it should be like this:
def produit_entier(a):
for x in a:
y=y*x
return y
Secondly, if you want to modify a value inside a function, which is not passed or declared inside the function - you gotta specify a global keyword to make it accessible for the modification (if you only want to read it - you do not have to specify global keyword):
def produit_entier(a):
global y
for x in a:
y=y*x
return y
Thirdly, you do not have to return a value of y though it is a global one, just print it after.
And fourthly, using global variables is actually a bad practice (since you might modify if accidentally somewhere you do not want to and it will be difficult to find). I suggest you either declare it inside the function:
def produit_entier(a):
y = 1
for x in a:
y=y*x
return y
Or just pass a value as an argument:
def produit_entier(a, y):
for x in a:
y=y*x
return y
Best of luck!
I'll provide an alternative answer using reduce:
from functools import reduce
def produit_entier(a):
return reduce(lambda x,y: x*y,a)
Or just the built-in reduce(int.__mul__, a)
I'm trying to pass information back and forth between 2 scripts. In one, we obtain a user input, in the other some modification is done to the user input, then back to the first one, we print out that modification.
#del2
def fun():
return int(user_input)+1
#script to run
user_input=input('some number')
from del2 import fun
print(fun())
So when we run our script, the user gives some input, the next line then runs the other script, which adds a value of 1 to the user inputted value, and then we print out that modified value. However, it appears you can't define a variable in one script, and have that defined variable transfer over to another script. Thus, I get this error when I try the above: NameError: name 'user_input' is not defined. I've tried to look at other posts regarding this, but they use tkinter and all are a bit too complicated/over my head to understand. So I made a very basic simple example to try and understand how this all works.
Edit:
I don't want to make another post, since its regarding the same issue. If I have to define every input used for every function, then it becomes quite crowded if you have multiple inputs. I.E.
#del2
def fun(user_input):
return int(user_input)+1
def fun2(user_input2):
return int(user_input2)+1
def fun3(user_input3):
return int(user_input3)+1
def fun4(user_input4):
return int(user_input4)+1
def fun5(user_input,user_input2,user_input3,user_input4):
return fun(user_input)+fun2(user_input2)+fun3(user_input3)+fun4(user_input4)
#script to run
user_input=input('some number')
user_input2=input('some number')
user_input3=input('some number')
user_input4=input('some number')
from del2 import fun5
print(fun5(user_input,user_input2,user_input3,user_input4))
Is there a better way to do this, so fun5 doesn't become extremely long if you have multiple inputs.
You need to define fun so it takes the variable as a parameter: def fun(user_input) then pass that variable to the imported function.
Also if you want user_inputs value to change after you call your fun() function you need to something like this:
#del2
def fun(user_input):
return int(user_input) + 1
#script to run
user_input = input('some number')
from del2 import fun
user_input = fun(user_input)
print(user_input)
Edit:
The fun() function isnt for just user_input. So you can use the same fun() function for another variables.
#del2
def fun(any_input): # i changed the variables name just to be clear
return int(any_input) + 1
#script to run
user_input = input('some number')
user_input2 = input('some number')
from del2 import fun
user_input = fun(user_input)
user_input2 = fun(user_input2)
print(user_input + ", " + user_input2)
and you can add the input variables to an array and do something like
#del2
def fun(any_input):
return int(any_input) + 2
def fun1(any_input):
return int(any_input) * 2
def fun2(any_input):
return int(any_input) // 2
def fun3(any_input):
return int(any_input) - 2
def fun5(input_array):
functions = [fun, fun1, fun2, fun3]
final = 0
if len(input_array) != 4:
raise Exception("Not enough functions for inputs")
for i in range(len(input_array)):
final += functions[i](input_array[i])
return final
#script to run
user_inputs = []
user_inputs.append(input('some number 0: ')) #you can use a for loop here too
user_inputs.append(input('some number 1: '))
user_inputs.append(input('some number 2: '))
user_inputs.append(input('some number 3: '))
from del2 import fun5
user_inputs = fun5(user_inputs)
print(user_inputs)
You can do this using the global keyword and a global variable within the imported module that is accessed by the different functions. Taking a simpler example that just adds or subtracts from a globally stored total:
# tally.py
total = 0
def add(n):
global total
total += n
def subtract(n):
global total
total -= n
# test_tally.py
import tally
tally.add(5)
tally.subtract(1)
print(tally.total)
However, global variables are bad. We do not generally think in terms of passing data back and forth between modules. The imported module is executed in its entirety at the time of importing, so data can only be passed to functions or other objects within the imported module.
Instead, modules often include classes, which can be used to generate objects that can store state. Data can be passed to these objects and stored within them. The objects can then operate upon the data and return different results by calling different methods of the object. This would be written like this:
# tally.py
class Tally(object):
def __init__(self):
self.total = 0
def add(self, n):
self.total += n
def subtract(self, n):
self.total -= n
# test_tally.py
from tally import Tally
tally = Tally()
tally.add(3)
tally.subtract(4)
print(tally.total)
What I'm trying to do:
executing the script, I will have to type in two numbers and it will compare them.
I want to be asked a total of 3 times.
The first time I will type in 10 and 5, second time 5 and 10 and the third time I will type in 10 and 10 to get all three possible answers.
My problem with the first code is: getnumbers() is being called inside of Checknumbers().
I want to create functions and a loop and strictly ONLY execute the functions inside a dedicated loop and not within another function.
I want everything clean cut and no reference of any function inside another function, I don't want to use any global variables either.
I solved this with a class but I'm not really sure if I'm butchering the language or if this is common practice. Also I have to reference the class inside the checknumbers() function.
First solution:
def getnumbers():
x = input("Enter the X number: ")
y = input("Enter the Y number: ")
return x, y
def checknumbers():
x, y=getnumbers()
if x > y:
print(f'x is larger then y: x is {x} and y is {y}')
elif y > x:
print(f"y is larger then x: x is {x} and y is {y}")
elif y == x:
print(f"x is equal to y: x is {x} and y is {y}")
else:
print("Dont know mate")
n = 0
while(n < 3):
checknumbers()
n += 1
This is the variant with the class:
class ui:
x = input("Enter the X number: ")
y = input("Enter the Y number: ")
def checknumbers():
if ui.x > ui.y:
print(f'x is larger then y: x is {ui.x} and y is {ui.y}')
elif ui.y > ui.x:
print(f"y is larger then x: x is {ui.x} and y is {ui.y}")
elif ui.y == ui.x:
print(f"x is equal to y: x is {ui.x} and y is {ui.y}")
else:
print("Dont know mate")
n = 0
while(n < 3):
checknumbers()
n += 1
Ideal solution, so both functions getnumbers() and checknumbers are clean cut independent of each other and they are being called inside the while loop, the problem is that x and y from the getnumbers() function are unknown to checknumbers.
The requirement is: I cant have any reference to any other function inside my functions, how do I pass x and y without referencing them?:
def getnumbers():
x = input("Enter the X number: ")
y = input("Enter the Y number: ")
return x, y
def checknumbers():
if x > y:
print(f'x is larger then y: x is {x} and y is {y}')
elif y > x:
print(f"y is larger then x: x is {x} and y is {y}")
elif y == x:
print(f"x is equal to y: x is {x} and y is {y}")
else:
print("Dont know mate")
n = 0
while(n < 3):
getnumbers()
checknumbers()
n += 1
You're getting confused between classes and instances, and between class attributes and instance attributes. (Read e.g. this)
The OO way to store state variables (like x,y) so you don't have to pass them around between function(/method) calls is to make them instance attributes. (Not class attributes, as you were doing. Don't worry, I did that too when I first learned Python).
So we declare a class UI; we will access its instance attributes as self.x, self.y inside its methods.
Don't try to directly do stuff on class UI. You must instantiate it first: ui = UI(). You should follow the Python convention that class names are Uppercase/CamelCase: UI, instance names are lowercase e.g. ui, ui1, ui2...
You were trying to put code directly into the class definition of UI, not define methods and put the code in that, and your UI class didn't even have an __init__()
Methods are functions inside a class, they always have a first argument self. If they didn't, the method wouldn't be able to access the rest of the class(!)
Now that we cleared that up, there are a couple of ways to decompose the methods to do what you want to do:
Have an empty __init__() (you could just make its body do pass). Have get_numbers() and check_numbers() be separate methods, which you manually call in-order. This is what I show below and is closest to what you said you want ("I want no reference to any function inside another function"), but is bad decomposition - what if the client called check_numbers() before get_numbers()? It would blow up on TypeError since __init__() initializes x,y with None.
Better would be to have __init__() call the method get_numbers() under-the-hood to guarantee the instance gets properly initialized. (We could always call get_numbers() again later if we want to input new numbers). That's easy to change, I leave that to you.
In approach 1., we had to initialize the instance members to something (otherwise trying to access them in check_numbers() will blow up). So we initialize to None, which will deliberately throw an exception if we compare. It doesn't really matter, this is just bad decomposition to not have __init__() properly initialize the instance (and call whatever methods it needs to to get that done). That's why approach 2. is better. Generally you should always have an __init__() that initializes the class into a known state, so that any other method can safely be called.
Code:
class UI:
def __init__(self, x=None, y=None):
self.x = x
self.y = y
def get_numbers(self):
self.x = input("Enter the X number: ")
self.y = input("Enter the Y number: ")
def check_numbers(self):
"""This is bad decomposition because if the client calls check_numbers() before get_numbers(), the NoneType will throw a TypeError"""
if self.x > self.y:
print(f'x is larger then y: x is {self.x} and y is {self.y}')
elif self.y > self.x:
print(f'y is larger then x: x is {self.x} and y is {self.y}')
elif self.y == self.x:
print(f'x is equal to y: x is {self.x} and y is {self.y}')
else:
print("Don't know mate")
# Declare an instance and reuse it three times
ui = UI()
for n in range(3):
ui.get_numbers()
ui.check_numbers()
Also, some minor stylistic points:
you don't need a while-loop for a simple counter: n = 0, while(n < 3) ... n += 1 . A for-loop is a one-liner: for n in range(3):
good Python style (see PEP-8) is to name the methods lower_case_with_underscores, thus get_numbers(), check_numbers()
a great top-down way to design a class is to write its method signatures first, think about what methods and attributes you'll need and how they'll work together. Example: "get_numbers() will get the user input, hence we'll need attributes self.x,y to store the numbers so check_numbers() can access them". And this way you should hit any problems with class design before you've written a wall of code.
If you don't want to call getnumbers() within checknumbers(), the only alternative that makes sense is to pass the numbers as parameters to checknumbers().
def getnumbers():
x = int(input("Enter the X number: "))
y = int(input("Enter the Y number: "))
return x,y
def checknumbers(x, y):
if x > y:
# etc.
...
for _ in range(3):
x,y = getnumbers()
checknumbers(x,y)
That at least has better separation of concerns.
I don't see anything wrong with the first solution (except for the fact that getumbers returns strings in Python 3) . Classes are not the solution for every problem
I cant have any reference of any other function inside my functions, how do I pass x and y without referencing them?
It's impossible to pass something without referencing it. Even if x and y were global variables (which is much worse than your current design) the using function would need to reference them.
I don't understand why you are under the impression that calling a function inside another function is bad or wrong design.
I am getting an error when I try to run this simple python script:
def ask_x():
x = int(input('What is X?'))
def ask_y():
y = int(input('What is Y?'))
def result():
print(z)
def count():
if (x>10):
z = x + y
else:
z = 0
print('nono')
#start of program
ask_x()
ask_y()
count()
result()
I am using Python 3. I tried searching the forum and found Stackoverflow - input() error - NameError: name '…' is not defined
but it doesn't work for me.
This is because your variables are in a local scope. You can't access x outside of the ask_x() function.
I would suggest you read up on functions to get a better grasp of this.
def ask_x():
return int(input('What is X?'))
def ask_y():
return int(input('What is Y?'))
def result(z):
print(z)
def count(x, y):
if (x>10):
return x + y
else:
print('nono')
return 0
#start of program
x = ask_x()
y = ask_y()
z = count(x, y)
result(z)
This will grab the values in each function, however, instead of storing them in the local scope, it'll be returned to the main function and stored in the corresponding variable.
You can then send x and y as parameters to count(), take care of your logic, and return the the value to be stored as z.
I hope this makes sense!
One way to get around scoping is to return the variable you need from your function and pass it in where needed. I prefer this to using global variables:
def ask_x():
return int(input('What is X?'))
def ask_y():
return int(input('What is Y?'))
def result(z):
print(z)
def count(x,y):
if (x>10):
z = x + y
else:
z = 0
print('nono')
return z
#start of program
x = ask_x()
y = ask_y()
z = count(x,y)
result(z)
It would be better to use one of the ways presented in How to ask user for valid input to get to your input:
def askInt(text):
"""Asks for a valid int input until succeeds."""
while True:
try:
num = int(input(text))
except ValueError:
print("Invalid. Try again.")
continue
else:
return num
x = askInt("What is X?")
y = askInt("What is Y?")
This way you pass in the changing value (the text) and both profit from the variable parsing and validation.
If you dont want to return then just initialize variable with some default values
x=0
y=0
z=0
def ask_x():
global x
x = int(input('What is X?'))
def ask_y():
global y
y = int(input('What is Y?'))
def result():
global z
print(z)
def count():
global x,y,z
if (x>10):
z = x + y
else:
z = 0
print('nono')
#start of program
ask_x()
ask_y()
count()
result()
Python follows function scoping unlike some other languages like c which follows block scoping. This implies variables defined inside a function cannot be accessed outside. unless they are defined global.
Solution to your problem:
You can either return them in your functions and store them in variables in global scope or put all the input statements inside a single function.
So here is the the problem
def func_1(x):
print 'function'
def func_2(x,y):
print 'function2'
def func_3():
n=func_1(x)
m=func_2(x,y)
i have 2 functions and i have a third one which needs to use the first 2 , the problem is that i don't know how to make it work . I give the arguments of the first two functions and it gives me an error , tried giving the functions as an argument , but it gives me a syntax error
i also tried of getting rid of the first function , solving the problem with a while cycle like this
counter = 0
while counter<10:
n=func_1(x)
m=func_2(x,y)
but it tells me that tuple object is not callable
If someone could tell me how to do it without defining the first 2 functions inside the third one i would be grateful
You are not passing func_3() any arguments, and still expecting it to know x and y
Also func_1 () and func_2 doen't return anything, so there is no need to do value = func() at func_3()
Try this:
def func_1(x):
print "i'm func1"
print x
def func_2(x,y):
print "i'm func2"
print x, y
def func_3(x, y):
func_1(x)
func_2(x, y)
func_3(1, 2)
It's hard to tell from your question, but it sounds like you are trying to get func3 to use functions passed as arguments? Something like
def func1(x):
return 2*x
def func2(x, y):
return 3*x + 2*y
def func3(x, y, fn1, fn2):
return fn1(x) + fn2(x, y)
def main():
print(5, 8, func1, func2)
if __name__=="__main__":
main()