Multiple return values in python - python

I want to change a python function to return two values. How do I achieve that without affecting any of the previous function calls which only expect one return value?
For eg.
Original Definition:
def foo():
x = 2
y = 2
return (x+y)
sum = foo()
Ne Definition:
def foo():
x = 2
y = 2
return (x+y), (x-y)
sum, diff = foo()
I want to do this in a way that the previous call to foo also remains valid?
Is this possible?

def foo(return_2nd=False):
x = 2
y = 2
return (x+y) if not return_2nd else (x+y),(x-y)
then call new version
sum, diff = foo(True)
sum = foo() #old calls still just get sum

By changing the type of return value you are changing the "contract" between this function and any code that calls it. So you probably should change the code that calls it.
However, you could add an optional argument that when set will return the new type. Such a change would preserve the old contract and allow you to have a new one as well. Although it is weird having different kinds of return types. At that point it would probably be cleaner to just create a new function entirely, or fix the calling code as well.

I'm sorry to tell you, but function overloading is not valid in Python. Because Python does not do type-enforcement, multiple definitions of foo results in the last valid one being used. One common solution is to define multiple functions, or to add a parameter in the function as a flag (which you would need to implement yourself)

Related

Can I use one argument as the default argument in the same function? [duplicate]

I want to define a resize(h, w) method, and I want to be able to call it in one of two ways:
resize(x,y)
resize(x)
Where, in the second call, I want y to be equal to x. Can I do this in the method definition or should I do something like resize(x,y=None) and check inside:
if y is None:
y = x
Can I do this in the method definition
No. During the method definition there's no way to know what value x might have at run-time. Default arguments are evaluated once at definition time, there's no way to save a dynamic value for y.
or should I do something like resize(x,y=None) and check inside
exactly. This is a common idiom in Python.
To complete Jim's answer, in the case that None is valid as a parameter value, you could use variable length arguments feature (positional, and/or keyword). Example of use for positional:
def resize(x,*args):
if args:
if len(args)>1:
raise Exception("Too many arguments")
y = args[0]
else:
y = x
in that example, you have to pass x, but you can pass 0 or more extra positional arguments. Of course you have to do the checking manually, and you lose the y keyword.

Update the referred variable in dictionary is not working [duplicate]

How can I pass an integer by reference in Python?
I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.
How can I pass an integer into a function by reference?
What are the best practices?
It doesn't quite work that way in Python. Python passes references to objects. Inside your function you have an object -- You're free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:
def change(x):
x[0] = 3
x = [1]
change(x)
print x
This is ugly/clumsy at best, but you're not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).
Understanding this, we can see why there is no way to change the value of an immutable object inside a function -- you can't change any of its attributes because it's immutable, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.
Usually the workaround is to simply return the object that you want:
def multiply_by_2(x):
return 2*x
x = 1
x = multiply_by_2(x)
*In the first example case above, 3 actually gets passed to x.__setitem__.
Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A "best practice" is to use multiple return values, which is much easier to do in Python than in languages like Java.
Here's a simple example:
def RectToPolar(x, y):
r = (x ** 2 + y ** 2) ** 0.5
theta = math.atan2(y, x)
return r, theta # return 2 things at once
r, theta = RectToPolar(3, 4) # assign 2 things at once
Not exactly passing a value directly, but using it as if it was passed.
x = 7
def my_method():
nonlocal x
x += 1
my_method()
print(x) # 8
Caveats:
nonlocal was introduced in python 3
If the enclosing scope is the global one, use global instead of nonlocal.
Maybe it's not pythonic way, but you can do this
import ctypes
def incr(a):
a += 1
x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref
Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you're passing in to the function?
If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson's answer demonstrates.
If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can't think of anything, go back and read the sentence again a few times, and then use the list.
More generally, if you're trying to port some Java idiom directly to Python, you're doing it wrong. Even when there is something directly corresponding (as with static/#staticmethod), you still don't want to use it in most Python programs just because you'd use it in Java.
Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:
def inc_i(v):
v.i += 1
x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it's a more convenient by-reference number container than a single-element list.
import numpy as np
def triple_var_by_ref(x):
x[0]=x[0]*3
a=np.array([2])
triple_var_by_ref(a)
print(a+1)
output:
7
The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.
class Thing:
def __init__(self,a):
self.a = a
def dosomething(ref)
ref.a += 1
t = Thing(3)
dosomething(t)
print("T is now",t.a)
In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.
Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.
class PassByReference:
def Change(self, var):
self.a = var
print(self.a)
s=PassByReference()
s.Change(5)
class Obj:
def __init__(self,a):
self.value = a
def sum(self, a):
self.value += a
a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2
In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that's passed to a method.
integers are immutable in python and once they are created we cannot change their value by using assignment operator to a variable we are making it to point to some other address not the previous address.
In python a function can return multiple values we can make use of it:
def swap(a,b):
return b,a
a,b=22,55
a,b=swap(a,b)
print(a,b)
To change the reference a variable is pointing to we can wrap immutable data types(int, long, float, complex, str, bytes, truple, frozenset) inside of mutable data types (bytearray, list, set, dict).
#var is an instance of dictionary type
def change(var,key,new_value):
var[key]=new_value
var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])

The point of use of return statement

I'm curious of what's the point of using return statement.
def give_me_five():
five = 5
return five
number = give_me_five()
print("Here's what I got from give_me_five():", number)
Above code shows the following result.
Here's what I got from give_me_five(): 5
As you can see, when you can just type 5 in print("Here's what I got from give_me_five():", 5) like this, what's exactly the point of using return statement and why does it need to even make a function to set a value 5?
Why you need return
Try removing return. It then prints
Here's what I got from give_me_five(): None
If you do not return 5, you have no way to recover it outside your function.
That is why you need return. But then...
Why you need functions
In your example, your function always returns the same value, so it is not needed, but suppose you have a more complex function that returns based on an input.
def give_me_more(n)
return n + 1
This function does not always return the same value, so it is a bit more useful. But then you should ask: wait, can't I just replace that function by n + 1 in my code?
Can't we do without function?
Well yes, but keep in mind that functions can be way more complex than the above examples.
def get_factors(n):
factors = []
for i in range(int(math.sqrt(n))):
if n % i == 0:
factors.append(i)
factors.append(n / i)
return sorted(factors)
Do you want to insert this code in your script everytime you want to get the factors of a number? Of course not, and to be able to reuse code you need to write functions. Which in turn requires return.

Handle differing number of returned variables

I am looking for handling differing number of returned values from invoked functions in a set number of target variables. The following simplified snippet is a starting illustration:
def f1(): return 1,2,3
def f2(): return 4,5
a,b,c = f1()
a,b,c = f2() # How to massage this call: default of some sort?
So the objective would be to unpack either 2 or 3 results into three output variables.
Consider that the f() being invoked may be one of (many functions..) that mostly all return only two variables .. but there is a need to add a third parameter to maybe one or two of them.
The motivation here: an existing codebase that presently returns only two variables. But I need to add a third one. It would be helpful to leave the existing code mostly alone and simply handle the missing third parameter gracefully.
What construction could be used here?
Generally, you could save all of the returned values to a single variable and then access them using indexing.
x1 = f1() # x1[0] = 1, x1[2] = 2, etc.
x2 = f2()
For Python 3:
If you need to use a,b,c for separate pieces of code, you can pack the variables using:
a,b,*c = f1()
a,b,*c = f2()
This will capture all values beyond the first 2 returned by f1 or f2 as a list in c.
Any python:
If you are in version 2.7, you can take a few extra steps to ensure assigning c doesn't give an error. You capture the output of your function as a list, then extend the list to the length of your variables using None. After that, you can assign directly to a,b,c
# assumes you have 3 variables: a,b,c
res = list(f2())
res += [None]*(3-len(res))
a,b,c = res
You are unpacking the result of those two functions, instead of doing that perhaps you could assign the result to a single variable then test that for length. much like here: ValueError: need more than 2 values to unpack in Python 2.6.6
t = list(f2())
if len(t) > 2:
# Can use the third result!
c = t[2]

Need help using a mutator function in python

So I need to use a mutator method to change elements of a list in Python. I would normally do this using a function that can return a value, but for this assignment we are not allowed to return any values in the function.
Here's an example of the general idea that i'm talking about
def changeX(x):
x = 5
x = 3
changeX(x)
print(x)
The output for this would obviously be 3 since I did not change x.
So my question is, how would I approach this assignment? I need to use the mutator method to modify my variable but I'm not sure how.
You get the results you do because you pass a primitive value into your "mutator" function.
If you pass in a list, you'll see that you can change the value in place:
def changeX(x):
x[0]=3
x = [1,2,3]
changeX(x)
print (x)
It will print [3,2,3]. Check it out:
https://repl.it/EIZW/0

Categories

Resources