I have set a string called 'charge' within a function but when I call 'charge' in the main body I get a traceback call saying that 'charge' is not defined. I would like to know if it is possible to call the string from outside of the function and if it is not, is there another way to get the data held within charge?
def service (x, y, z):
print ('How many animals are being provided for?')
nodogs = input ('-----> ')
if nodogs == '1':
charge = 'x'
elif nodogs == '2':
charge = 'y'
elif nodogs == '3':
charge = 'z'
x = int (x)
y = int (y)
z = int (z)
# the call for the string is later on but I think that part is irrelevant.
#If it is not, please say and I will post it.
I am a novice and am only trying out simple code. if an advanced feature is required, please explain the feature as I am unlikely to know it already,
Thanks in advance - TGSpike
You should put the line
return charge
at the end of the function, and then when you call the function, do
charge = service(x, y, z)
(with x y z set however you're using them). This will return the value of charge to your main program, and put it in the variable charge. If you want to do this with multiple variables, you can do
return x, y
and
x, y = service(x, y, z)
This is called tuple unpacking.
Related
Premise:
Suppose I have a variable x and two function f(x) and g(x)
such that when f(x) has the ability to change the value of x (maybe it wants to keep track on how many times f(x) has been called) and g(x) doesn't want to change the value of x at any cost.
Now if i was choose x as an integer, I can accomplish g(x) and if x is a list, I can accomplish f(x).
Question:
But what if I want to accomplish both of them in the same program?
What should I do then?.
If its not possible, then doesn't this severely handicap python wrt other languages.
Note:
Basically my question is motivated by finding the drawbacks of not having pointers in python as in other language like C++, the above task can easily be implemented by choosing the *x instead of x.
If all you need to do is change the value of a variable that you pass to f, you can simply return the new value:
def f(x):
return x + 1
x = 30
x = f(x)
# x is now 31
If there is already another value you need to return from f, you can return a tuple and unpack the return value to multiple variables:
def f(x):
return 46, x + 1
x = 30
y, x = f(x)
# x is now 31
In C++, the use of pointers that you bring up compensates for the fact that it's relatively difficult to return multiple values from a function. In Python, while we're still technically returning one value, it's much easier to create tuples and unpack them.
You could make your own class:
`class some_class():
self._value = 0
self._access_counter = 0
def update_value(self):
<your code here>
def get_value_by_ref(self):
self._access_counter += 1
return self._value
`
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.
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.
I made a quick script below to test some behaviors after encountering a problem on a larger self learning initiative. I am using python 2.7.x.
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y
y = int(raw_input('Enter: '))
test(y)
print 'Outside the function', y
Enter: 6
Inside the function 36
Outside the function 6
However, when the code is as below:
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y
y = test(6)
print 'Outside the function', y
Inside the function 36
Outside the function 36
Why does the first code snippet provide 36, 6 and not 36, 36 as in the second case? What suggestions can you make for the function to return the altered value (in this case 36) so that value can be passed into another function.
For context, what I am aiming to do is have the user input a value, send that value to a function. I want that function to perform some logic upon that input, for example test to make sure it meets a certain condition: uses characters [a-zA-z -], then return that value, so that it can be passed to another function. However, I am not asking for support in this
Many thanks for your time, any help is greatly appreciated.
case #1 explained
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y; # returning 36
y=int(raw_input('Enter: ')) # here y is 6 as you read from user
test(y) # you are passing 6 and which computes y to be 36, though test is returning 36, but it is not stored in any variable (including y). (not re-assigned, so outside the definition/fucntion, y is still 6)
print 'Outside the function', y # so it is still 6
Case #2 explained
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y; # returning 36
y=test(6) # here you received and stored it in y
print 'Outside the function', y # now y is 36
Because you changed the value of y on the second example by setting y = test(6). Set y = test(y) on the first and you will get the same result.
The only difference between the two snippets is that in the second one you reassign y to to the result of calling the function. That is all you need to do.
In the first code, you have a global variable named y, which you assign the value 6 to. When going into the function, you create a local variable, also called y, which you assign the value 6*6=36 to. When you leave the function, you return this value, but do not use it. Then, you print the global y.
In the second code, you assign the returned value (local y = 36) to your global value y, thus making the two printed values to be the same.
Why does the first code snippet provide 36, 6 and not 36, 36 as in the second case?
Because you defined an entirely new y variable whose value is 36, meanwhile the value outside the function is 6.
In the second case, you still have two y variables, but the one towards the bottom (almost said first one, because it technically is executed first) is the return value of the method
You don't assign the result of test(y) the variable y in your code
y=int(raw_input('Enter: '))
# y= 6
# here you need to assign y= test(y)
test(y)
# test result is 36, but not saved to y
print 'Outside the function', y
# print 6
There are two reasons the output is not the same:
- the scopes are different, in your first example, the y you assign in the function is not the same the y outside of it, even if they have the same name. To (over)simplify, you can think that, when you start a new function, there is a brand new memory space created and, inside of it, there is nothing already present (except the modules names imported, the argument to the function, ...), so, even if you do an assignation to y inside the function, it is a brand new y, and, its life stops when the function is over.
- in the second example, you take to output of your function and put it in y, in the first example, the output is lost since not used.
To illustrate my first point:
#!/usr/bin/python
def test(arg1):
y = arg1 * arg1
print 'Inside the function', y
return y;
test(3)
print y
This will raise NameError, because, outside the function, y does not exists.
I invite you to read and understand this very simple explanation Getting Started with Python - Variable scope
I have a small piece of code to understand how to return values that can be used in other sections of the code. In the following i only want to return the variable z, or the value snooze. But it does not work. Please can someone help me to understand why this will not work?
import time
def sleepy(reps, snooze):
t = []
for x in range(reps):
x = time.time()
time.sleep(snooze)
y = time.time()
z = y - x
t.append(z)
print 'difference = ', z*1000
print 'total:', (sum(t)/reps) * 1000
return z
sleepy(10, 0.001)
print z # does not like this.
If I print snooze it also grumbles. Why is that?
z is a local variable in your sleepy() function; it is not visible outside of that function.
Your function does return the value of z; assign it:
slept = sleepy(10, 0.001)
print slept
I used a different name here to illustrate that slept is a different variable.
You should not try to print z or snooze because they have a scope that is limited to the definition of the function. When you do: sleepy(10,0.001) then the value 10 is assigned to reps and the value 0.001 is assigned to snooze.
And then the things that you want are done with these variables. In the meantime a new variable called z is created with the scope inside the definition of the function. And then this value is returned. And as soon as the last statement has been executed then all the variables that are created inside the definition are deleted.
So you must do:
a = sleepy(10,0.001)
print a
This will print the value of a which is the value that you returned from inside the function.
Also you can print z if you declare it as global, that is:
import time
def sleepy(reps, snooze):
t = []
for x in range(reps):
x = time.time()
time.sleep(snooze)
y = time.time()
global z ##notice this line has been changed.
z = y - x
t.append(z)
print 'difference = ', z*1000
print 'total:', (sum(t)/reps) * 1000
Now the value to be returned is in z and you can print it as so:
sleepy(10,0.001)
print z
When you return something from a function you are calling, the syntax is as follows:
p = sleepy(10,0.001)
print p
z and snooze are local variables to the function.
You need to assign the result of the function to a variable to have it available after the function call.
z is a local variable.when you return z it not actually returns variable z instead its
returns the value which is present in z so u need to store it in another variable and print that variable
or you can just use
print sleepy(10, 0.001)