I have this method that takes in an unknown number of args and I have some variables from another class that I want to match the arg variable name to. The variable names are the same across this current class and the OtherClass. I was thinking something like:
def my_method(self, *args):
for arg in args:
OtherClass.arg_variable_name = arg # where "arg" on the right is the value
How could I do this effectively in python?
I think you should use **kwds instead of args. *args are values, so the caller can send it not with the variable, but just value itself.
my_object.my_method(1, 2, 3, "string")
If you use **kwds, you'll know the key, value pairs.
You could use something like
dict( (name,eval(name)) for name in['self','args']
To get a dict with the values for each argument, and then from there you could match the dict values with your respective arg variable name.
Related
This question already has answers here:
Access an arbitrary element in a dictionary in Python
(14 answers)
Closed 3 years ago.
I have a function, which has a signature like this:
def func(**kwargs):
The user of that function will call the function with zero or one keyword arguments. If he passes one argument, the name will be foo_id, bar_id, baz_id etc., but I don't know the exact name he will use. The value of the passed argument will be some interger. I still want to take that argument's value and use it.
Currently I'm doing it like this, but I was wondering would there be a cleaner way to achieve this:
def func(**kwargs):
if kwargs:
target_id = list(kwargs.values())[0]
else:
target_id = None
# use target_id here, no worries if it's None
I'm using Python 3.8, so backwards compatibility is not an issue.
Here we are
def func(**kwargs):
target_id = next(iter(kwargs.values()), None)
print(target_id)
func(name_id='name')
func(value_id='value')
func(test_id='test')
func()
Outputs
python test.py
name
value
test
None
Since the dictionary has only one item, and you don't need to keep it in the dictionary, the cleanest way is to use the dict.popitem method. This returns both the argument name and its value as a pair.
def func(**kwarg):
if kwarg:
name, value = kwarg.popitem()
# ...
else:
# ...
Since the caller should supply at most one argument, I recommend explicitly raising an error if it is called with more arguments:
def func(**kwarg):
if len(kwarg) > 1:
raise TypeError(f'Expected at most 1 keyword arg, got {len(kwarg)}.')
elif kwarg:
name, value = kwarg.popitem()
# ...
else:
# ...
I was just testing a piece of code with kwargs and args. But why args is picking up all the passed parameters in the following code ?
def myfunc(color='red',*args,**kwargs):
print (args)
print (color)
print (kwargs)
names=["Ramesh","Krishna"]
ages={'Ramesh_age':20,'Krishna_age':10,'Kanchi_age':5}
myfunc('blue',names,ages)
Result:
(['Ramesh', 'Krishna'], {'Krishna_age': 10, 'Ramesh_age': 20, 'Kanchi_age': 5})
blue
{}
why it all including ages has been assigned to ages and kwargs is empty ?
You need to use *names to unwrap names and **ages to unwrap ages.
Like this myfunc('blue', *names, **ages)
To be precise, kwargs is not picking up any values because kwargs looks for key - value pairs.
The way you passed your arguements, there is no key value pairs. You passed along
ages={'Ramesh_age':20,'Krishna_age':10,'Kanchi_age':5}
as a whole object, instead of destructuring the object and passing it as individual key value pairs.
As others have pointed out, the correct way is to destructure the object as seperate key value pairs as:
**ages
args looks for any values and kwargs looks for any key-value pairs. When you call your function, you have to specify * before args and ** before kwargs. It is the way Python works.
Here's your code:
def myfunc(color='red',*args,**kwargs):
print (args)
print (color)
print (kwargs)
names=["Ramesh","Krishna"]
ages={'Ramesh_age':20,'Krishna_age':10,'Kanchi_age':5}
# to call the function
myfunc('blue', *names, **ages)
Here's the results:
('Ramesh', 'Krishna')
blue
{'Ramesh_age': 20, 'Krishna_age': 10, 'Kanchi_age': 5}
Explanations can be found here and here
While applying some external module method to a class I need to be able to pass different pairs of arg = 'value' to the function, like:
Ad.nodes.get(id_ = '11974312')
How to pass dicts or tuples to the function, so that it recognises 'id_' (string) as id_ (argument) in
('id_', '11974312') (tuple) or {'id_':'11974312'} (dictionary) ?
Basically, I just need to get id_ out of 'id_'
For your reference, I am trying to use neomodel module for neo4j graph db.
If I understand your question correctly, you are looking for the ** operator.
Example:
kwargs = {'first': 3, 'second': 6}
def add(first, second):
return first + second
print(add(**kwargs) == 9)
This will print True. When you apply ** to a dict argument, it will be decomposed into keyword arguments.
The argument name can be read as string using inspect.signature(function name).parameters.keys() where function name is a name of function, which argument need to be read as string
Example:
import inspect, itertools
dictionary={'id':'David','ip':'11.1.1.20'}
def func(id,ip):
func_argument = list(inspect.signature(func).parameters.keys() )
print(func_argument)
#Print the value from dic for each argument which is key in dict
for i in func_argument:
print(dictionary[i])
func(id=100,ip=200)
Say I have a list of similar functions:
def func1(a)
foo(a=a)
def func2(b)
foo(b=b)
...
the only difference of them is the argument name of foo, is that a short way to define them as one function, such as passing a argument name to the functions?
You can do it by unpacking a keyword argument dictionary:
def combined(name, value):
foo(**{name:value})
Then combined('a', a) is equivalent to func1(a). Whether this is a good idea is a separate consideration.
I saw the following code:
def __init__(self, fn, **kw):
[setattr(self,k,v) for (k,v) in kw.items()]
......
What does the input argument **kw mean?
kw is bound to a dict mapping keyword argument names to their values.
Try calling
def return_kwargs(**kw):
return kw
as return_kwargs(foo=1, bar="2", baz="hamspamspam").
Suppose you have a dict kw = {'a':1,'b':2}, then calling myfunction(**kw) is equivalent to calling myfunction(a=1,b=2).
This particular construction means what all keyword arguments for the constructor will end up as object attributes.
foo = Foo( func, bar = 1, baz = "aa" )
this would create an object with attribute "bar" set to 1 and "baz" to "aa"
Inside the function, kw is a dictionary that contains all the keyword=value arguments that you gave to your function:
def demo(**kw):
print kw
demo(a=1, b="hello")
Run the above and it will display a dictionary with two keys, a and b. So it works as a way to accept any keyword argument you decide to use when you call the function.
That's what it does. Why would anyone want to do that? Perhaps in a function that calls another function (given as a separate argument), and **kw is to hold options for the second function.