I'm new in Python and wants to know if there is a simple way to get amount of passed parameters in Python function.
a(1, 2, 3) ==>3
a(1, 2) ==>2
def a(*args, **kwargs):
print(len(args) + len(kwargs))
You can do this by using locals()
It is important to note, that this should be done as ultimately, your first step in your method. If you introduce a new variable in your method, you will change your results. So make sure you follow it this way:
def a(a, b, c):
# make this your first statement
print(len(locals()))
If you did this:
def a(a, b, c):
z = 5
print(len(locals()))
You would end up getting 4, which would not be right for your expected results.
Documentation on locals()
you could also change the input for your function to a list, so to have a function:
a(your_list)
then to know how many arguments have been passed to the function,
you could simply do:
print len(your_list)
However, this means that you change the input type for your function,
from many input variables to only one, the list(which can have a variable number of elements).
Related
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'])
I was wondering if there is a way to take the elements in a list and insert them into the inputs of a function. So for example
def function(x,y,z):
#does stuff
def main():
changing_list=[8,9,10]
function(changing_list)
I am using the function GetRows in Spotfire, which allows different amounts of input to be used. So I am planning to put the names of rows I am going to use into the list and then use it to give the inputs into the function. If there is a better way of doing this please tell me, I can't put in the inputs before hand due to me not knowing which rows I will be using beforehand. If there is something unclear please ask me to clarify. An important point that I noticed that I may have left out after looking at the answers. I cannot adjust the code in the function due to me not have access to it. Also the function might not always accept 3 inputs, it will vary depending on the what happens when the code runs before hand, the list may have 5 elements in one run and 1 element in the next one.
Change the line of:
function(changing_list)
To:
function(*changing_list)
If you're in Python 3.
Use:
function(l[0], l[1], l[2])
For this you can use the single star * which unpacks the sequence. This allows you to do this:
def mul(x, y):
return x * y
nums = (1, 5)
s = mul(*nums)
This will unpack the tuple. It actually executes as:
s = mul(1, 5)
You have requested 3 variables for your function when defining it, but you only give it one list. Try this:
def function(xs):
xs[0] = 1
xs[1] = 2
xs[2] = 3
def main():
changing_list = [8, 9, 10]
function(changing_list)
Now your function will take your list, and change it to [1, 2, 3]. You can use print to check.
I have a list and a function f which returns a 3-tuple. I would like to capture the first two return values, and with the third, append to lst. I know I can do the following:
a, b, c = f()
lst.append(c)
but I would like a way not to have the extraneous variable "c". I know I can also do:
lst.append(f()[2])
but I do not want to throw away the other two return values.
Any suggestions?
Edit: I appreciate the answers provided, but the question, put more clearly, is to find a neat one-liner.
Assign the return value to a local variable before you append the result.
No, you can't catch two values and append the third in one statement; you only get one "verb" per command.
result = f()
lst.append(result[2])
What you want to do is not possible with a "one liner" (without using semi-colon to fit two statements on a single line) unless you change your function definition.
Specifically, define f() in the following way:
def f(list_to_append_to):
a = ...
b = ...
c = ...
list_to_append_to.append(c)
return a, b
Then:
a, b = f(mylist)
If your problem is not saving yourself with writing one more line of code, but you would just want the function call, the assignment and the appendix in a single statement, you could use a wrapper function:
def append_and_assign(mylist, myfunc):
a, b, c = myfunc()
mylist.append(c)
return a,b,c
and so you can call:
a,b,c = append_and_assign(lst, f)
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]
I have a list a = [1,2,3,4,5]. And I have a function, say, Func(x). I know that if I do Func(a) then the reference of a will be passed into Func(x). And if I do Func(a[:]), a new list will be created and passed into Func(x).
So my question is: Is it possible to only pass the first three elements into Func(x) by reference, like Func(a) (I don't want to pass the whole list a into function due to certain reason)? If I do Func(a[:4]) a new list will be created and that's what I want to avoid.
The only way I can think about is to pass a and the indexes into Func(x), like Func(a, start, end).
There is no way to create a 'window' on a list, no.
Your only options are to create a slice, or to pass in start and end indices to the function and have the function honour those.
The latter is what the bisect module functions do for example; each function takes a lo and hi parameter that default to 0 and len(list) respectively:
def func(lst, lo=0, hi=None):
if hi is None:
hi = len(lst)
Why not create a second argument so that Func (a) becomes Func (a, n) where a is the reference to your array and n is the position in the array to which you want to evaluate to?
Something like:
Func (a, 2)
With that example the first three elements are evaluated.