Dynamically add keyword arguments - python

If I have a function:
def add(**kwargs):
for key, value in kwargs.iteritems():
print "%s = %s" % (key, value)
How can I dynamically add keyworded arguments to this function? I am building an HTML Generator in Python, so I need to be able to add keyworded arguments depending on which attributes the user wants to enable.
For instance, if the user wants to use the name attribute in a form, they should be able to declare it in a list of stored keyword arguments (don't know how to do this either). This list of stored keyword arguments should also contain the value of the variable. For instance, if the user wants the attribute name to be "Hello", it should look like and be passed to the function as so:
name = "Hello" (example)
Let me know if you guys need more information. Thanks!

You already accept a dynamic list of keywords. Simply call the function with those keywords:
add(name="Hello")
You can use the **expression call syntax to pass in a dictionary to a function instead, it'll be expanded into keyword arguments (which your **kwargs function parameter will capture again):
attributes = {'name': 'Hello'}
add(**attributes)

Related

Manipulating variables using globals() in python

I wanted to have the option to pass my arguments to a function in a concise manner. So instead of passing all arguments directly, I include them as parameters function definiton and pass all such arguments as Common_Args. Then I do the following
for key, value in Common_args.items():
if key in locals():
globals()[key] = value
Here is the problem. Even though the control goes inside the if condition(checked with debugger), the parameter's value do not change, but it should, right?
Guides have confirmed that this should work, and if I run single statements in my debugger, the value of the variable does change.
My function definition in more detail is
def plotLFPData1Channel(plotHandles=None, channelString="", stimulus_list=None, folderName=None, analysisType=None,
timeVals=None, plotColor=None, blRange=None, stRange=None, referenceChannelString=None,
badTrialNameStr=None, useCommonBadTrialsFlag=None ,*,Common_args=None):
# first we have to unpack common args
if Common_args is not None:
for key, value in Common_args.items():
if key in locals():
globals()[key] = value
and I call the function like so
result=plotLFPData1Channel(plotHandles=ax.flatten(), channelString=analogChannelString, stimulus_list=stimValsToUse,analysisType=analysisType,Common_args=commonArgs)
with commonArgs={"folderName":folderName , "timeVals":timeVals, "plotColor":plotColor, "blRange":blRange, "stRange":stRange, "referenceChannelString":referenceChannelString, "badTrialNameStr":badTrialNameStr, "useCommonBadTrialsFlag":useCommonBadTrialsFlag}

Passing default values to **kwargs

I have a function that returns some data, what I need to do in order to get the data is to pass an SQL-like query to the build_query variable.
def foo(client):
"""
API service that returns JSON data and accepts arguments
"""
report_query = (client.buildQuery()
.Select('Date','SearchEngine')
.From('Report_10')
.During('Yesterday')
get_report.downloadReport(
skip_header=True,
include_names=False,
get_summary=True,
get_totals=False)
What I am trying to do is make this function in to one that accepts **kwargs but has default arguments for the selected fields.
The idea is that I would be able to pass an argument to .During() and if I don't it defaults to Yesterday, I would be able to pass arguments to .Select(), for example .Select() would be .Select('Date','Device','StrategyType').
What I've tried and trying to understand:
def fn(**kwargs):
print(f"""
({kwargs['client']}.buildQuery()
.Select({kwargs['select']}))
.From({kwargs['report_type']})
.During({kwargs['during']})
get_report.downloadReport(
skip_header={kwargs['skip_header']},
include_names={kwargs['include_names']},
get_summary={kwargs['get_summary']},
get_totals={kwargs['get_totals']})""")
fn(client='10',select=['Date', 'SearchEngine'],report_type='new',during='Yesterday',skip_header=True)
Returns:
(10.buildQuery()
.Select(['Date', 'SearchEngine']))
.From(new)
.During(Yesterday)
get_report.downloadReport(
skip_header=True,
include_names=False,
get_summary=True,
get_totals=False)
Where I get stuck is trying to call fn() without any keyword arguments and wishing that the function would have default arguments for each field, such that it would look like the first code snippet in my question.
fn()
KeyError: 'client'
Is it possible to achieve something like this?
You can use the spread operator on dictionaries:
def func(**kwargs):
kwargs = {"printer": None, **kwargs}
This will set the value printer to none if it is not given.

possible variables of a method on python modules

I am new to python, my question is that how we can know the arguments name of a method on a module. for example, in the smpplib module page (https://github.com/podshumok/python-smpplib) i see an example code that has a line as below
client.bind_transceiver(system_id='login', password='secret')
I what to know how i can know that bind_transceiver function has system_id password (and system_type) variable.
help (smpplib.client.Client) just give me below info about bind_transceiver
:
bind_transceiver(self, **args)
Bind as a transmitter and receiver at once
tl;dr You would have to look at the source code or documentation to find out.
Explanation: bind_transmitter uses **args. This allows the person calling the function to pass in any number of keyword arguments. For example:
bind_transmitter() # valid
bind_transmitter(a=1, b='4') # valid
bind_transmitter(myarg=1, m=6, y=7, system_id='me', password='secret') # valid
As such, there is no way to know which keyword arguments bind_transmitter will actually use without examining the source code or documentation.
Sometimes, in Python, functions have **kwargs argument that means "any key - value argument is accepted".
Key-value pairs are passed as in your example:
client.bind_transceiver(system_id='login', password='secret')
The function implementation code access the key - value pairs with the dictionary kwargs. So the internal code would do something like:
def bind_transceiver(self, **kwargs):
# Do something with system id
print(kwargs['system_id'])
# Do something with password
print(kwargs['password])
The output of your call to this function would be
login
password
You can pass any key-value pair to the function but there are only 2 ways to understand which keyes will be actually consumed.
Read the function documentation
Read the code
The keyes that are not used will be stored anyway in the dictionary args within the scope of the function but they won't have any effect.
It is also possible that the function accepts another argument like *args. This, instead of a dictionary, will be read like a tuple by the function in a similar fashion but using positional numbers as keyes.

Difference between Positional , keyword, optional and required argument?

I am learning about functions in python and found many good tutorials and answers about functions and their types, but I am confused in some places. I have read the following:
If function has "=" then it's a keyword argument i.e (a,b=2)
If function does not have "=" then it's positional argument i.e (a,b)
My doubts :
What is the meaning of a required argument and an optional argument? Is the default argument also a keyword argument? (since because both contain "=")
Difference between the positional, keyword, optional, and required
arguments?
python official documentation says that there are two types of arguments. If so, then what are *args and **kargs (I know how they work but don't know what they are)
how *args and **kargs store values? I know how *args and
**kargs works but how do they store values? Does *args store values in a tuple and **kargs in the dictionary?
please explain in deep. I want to know about functions because I am a newbie :)
Thanks in advance
Default Values
Let's imagine a function,
def function(a, b, c):
print a
print b
print c
A positional argument is passed to the function in this way.
function("position1", "position2", "position3")
will print
position1
position2
position3
However, you could pass in a keyword argument as below,
function(c="1",a="2",b="3")
and the output will become:
2
3
1
The input is no longer based on the position of the argument, but now it is based on the keyword.
The reason that b is optional in (a,b=2) is because you are giving it a default value.
This means that if you only supply the function with one argument, it will be applied to a. A default value must be set in the function definition. This way when you omit the argument from the function call, the default will be applied to that variable. In this way it becomes 'optional' to pass in that variable.
For example:
def function(a, b=10, c=5):
print a
print b
print c
function(1)
and the output will become:
1
10
5
This is because you didn't give an argument for b or c so they used the default values. In this sense, b and c are optional because the function will not fail if you do not explicitly give them.
Variable length argument lists
The difference between *args and **kwargs is that a function like this:
def function(*args)
for argument in args:
print argument
can be called like this:
function(1,2,3,4,5,6,7,8)
and all of these arguments will be stored in a tuple called args. Keep in mind the variable name args can be replaced by any variable name, the required piece is the asterisk.
Whereas,
def function(**args):
keys = args.keys()
for key in keys:
if(key == 'somethingelse'):
print args[key]
expects to be called like this:
function(key1=1,key2=2,key3=3,somethingelse=4,doesnt=5,matter=6)
and all of these arguments will be stored in a dict called args. Keep in mind the variable name args can be replaced by any variable name, the required piece is the double asterisk.
In this way you will need to get the keys in some way:
keys = args.keys()
Optional arguments are those that have a default or those which are passed via *args and **kwargs.
Any argument can be a keyword argument, it just depends on how it's called.
these are used for passing variable numbers of args or keyword args
yes and yes
For more information see the tutorial:
https://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions

Use string variable **kwargs as named argument

I am trying to figure out a way to loop through a json config file and use a key name as the argument name to a method that uses **kwargs. I have created a json config file and used key names as methods. I just append "set_" to the key name to call the correct method. I convert the json to a dictionary to loop through any of the defaults. I want to pass argument names to **kwargs by a string variable. I tried to pass a dictionary but it doesn't seem to like that.
user_defaults = config['default_users'][user]
for option_name, option_value in user_defaults.iteritems():
method = "set_" + option_name
callable_method = getattr(self, method)
callable_method(user = user, option_name = user_defaults[option_name])
Calling the callable_method above passes "option_name" as the actual name of the kwarg. I want to pass it so that when "shell" = option_name that it gets passed as the string name for the argument name. An example is below. That way I can loop through any keys in the config and not worry about what I'm looking for in any method I write to accomplish something.
def set_shell(self, **kwargs):
user = kwargs['user']
shell = kwargs['shell']
## Do things now with stuff
Any help is appreciated I am new to python and still learning how to do things the pythonic way.
If I understand correctly what you're asking, you can just use the ** syntax on the calling side to pass a dict that is converted into kwargs.
callable_method(user=user, **{option_name: user_defaults[option_name]})

Categories