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)
Related
This question already has answers here:
Are the keys of a kwargs argument to Python function guaranteed to be type string?
(3 answers)
Closed 2 years ago.
what I want to do is like this
class Foo:
def __init__(self):
self.name = "james"
def foo(**kwargs):
for obj, new_name in kwargs.items():
obj.name = new_name
f = Foo()
foo(f="Tom") # f have to be recognized as an object not a string "f"
as my knowledge, kwargs is a dictionary.
I tested giving an object as key in dictionary. and dictionary can have an object as key.
dd = {f: 12}
print(dd)
>>>
{<__main__.Foo object at 0x00D685D0>: 12}
but when I give an object to function's parameter as key, it becomes just string "f".
Is there the way that doesnt' ruin the original syntax
function(obj=value, obj2=value2, ...)
not like this
function((obj, value), (obj2, value2), ...)
proper process to tuple
EDIT: use this code inside the function
obj = getattr(sys.modules[__name__], f"{obj_name}")
Apparently we cannot have anything else other than strings as key type.
Check detailed answer here : Are the keys of a kwargs argument to Python function guaranteed to be type string?
Check source code here:
https://github.com/python/cpython/blob/2ec70102066fe5534f1a62e8f496d2005e1697db/Python/getargs.c#L1604
kwargs as being a dictionary that maps each keyword to the value that we pass alongside it. That is why when we iterate over the kwargs there doesn’t seem to be any order in which they were printed out.
def myFun(**kwargs):
for key, value in kwargs.items():
print ("%s == %s" %(key, value))
# Driver code
myFun(first ='Geeks', mid ='for', last='Geeks')
you can go for **args
The ** symbol is used before an argument to pass a keyword argument dictionary to a function, this syntax used to successfully run the code when we don’t know how many keyword arguments will be sent to the function.
# function definition
def displayArgument(**arguments):
for arg in arguments.items():
print(arg)
# function call
displayArgument(argument1 ="hello", argument2 = 4,
argument3 ="code")
I am using a module for a project, I have to pass a function to the module and the model does something like:
class module:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(**dictionary)
And my function is something like:
def function(*foo):
return sum(foo)
The problem is that, the module needs named variables, and will pass it to the function like an unpacked dictionary, and the number of elements in dictionary can be variable, so I cannot pre-write the function as def function(x,y,z): return sum(x,y,z), and this raises an error. I do not wish to modify the module, because then, the code will not be universal. How can I solve this problem by just changing my code?
EDIT: I need foo as a list to use in the function
You module that you can't change is calling your function with:
function(**dictionary)
You won't be able to write your function to the argument is a list — it's not being passed a list. You can accept the keywords as a dict and the easily make a list. Your function just needs to be prepared to be called that way:
def f(**foo):
This leads to:
class module:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(**dictionary)
def f(**foo):
print(sum(foo.values()))
module(f, {'x':2, 'y':4, 'z':23})
# prints 29 as expected
def function(*args,**Kwargs):
try:
return sum(*args)
else:
return sum(**kwargs.values())
double * unpacked dictionary values, and one * is to unpacked anything(except dictionary).
The number and type of arguments are determined by code of function init
In your case this a single argument of type dictionary. So you have always to pass such function f(x) where x is a dictionary.
So the that is function f that deals with the argument.
E.g.
def fsum(x): return sum(x.values())
...
__init__(fsum, {'a': 1, 'b': 2, 'c': 3})
It seems you want the sum of the values:
def __init__(self, function, dictionary):
# dictionary is {'x':2, 'y':4, 'z':23}
function(dictionary.values())
The dictionary.values() will give a list of [2, 4, 23] for your example.
I want to call that function by extracting the first word from the string. For example my string is like:
"my_func arg_1 arg_2"
# ^ ^ ^ second argument of function
# ^ ^ first argument of function
# ^ name of the function
where my_func is a name of the function already defined.
Based on the above mention string, I want to dynamically execute the my_func function. So, my function call should be like:
my_func(arg_1, arg_2)
Currently I am trying to achieve this via using eval:
eval(command.split(' ', 1)[0])
How can I achieve this?
You may use locals() (or globals()) to fetch the reference of function based on string. Below is the sample example:
# Sample function
def foo(a, b):
print('{} - {}'.format(a, b))
# Your string with functions name and attributes
my_str = "foo x y"
func, *params = my_str.split()
# ^ ^ tuple of params string
# ^ function name string
Now, pass the function string as a key to the locals() dict with *params as argument to the function as:
>>> locals()[func](*params)
x - y # output printed by `foo` function
Regarding the split method, by default the delimiter is space so you don't actually need to define that your delimiter is space and as you want the first item in the list, you just need to type the index 0 [0].
locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.
var = "my_func arg_1 arg_2"
print (locals()[var.split()[0]]())
Or
var = "my_func arg_1 arg_2"
print (globals()[var.split()[0]]())
If the function was part of an object you could use the getattr built-in function.
var = "my_func arg_1 arg_2"
getattr(object, var.split()[0])
getattr(object, name[, default])
Return the value of the named
attribute of object. name must be a string. If the string is the name
of one of the object’s attributes, the result is the value of that
attribute. For example, getattr(x, 'foobar') is equivalent to
x.foobar. If the named attribute does not exist, default is returned
if provided, otherwise AttributeError is raised.
If you define you functions up front you can have greater control over their name mapping.
def my_func(a):
print(a)
functions = {'my_func': my_func}
def exe(text):
command = text.split(" ")
f = command[0]
args = command[1:]
if f in functions:
functions[f](args)
exe("my_func arg_1 arg_2")
Something along the lines of:
Check if the function exists inside the local scope.
If it does exist then run it using eval().
def add():
print("do something")
def find_function(funct_name, defined_names):
if defined_names.get(funct_name) is None:
print("no function called {}".format(funct_name))
return
eval(funct_name + "()")
# access local user defined names.
defined_names = locals()
#print(defined_names)
function_name = 'add'
find_function(function_name ,defined_names)
Output:
do something
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.
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.