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]})
Related
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.
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.
So, I would like to modify the json.loads() function to accept a new keyword parameter, but not have it just be a part of kwargs. In other words, I want it be an explicit part of the function's signature.
Here's my guess on how to do this. Are there better ways of doing this?
def json_to_python_syntax(json_method):
"""
Translate JSON-conforming key names to Pythonic standards on dict.
The goal of this decorator is to add a standard keyword parameter
'convert_syntax' onto the method. But, I'm not sure how to do this.
"""
#wraps(json_method)
def wrapper(json_string, convert_syntax=False, **kwargs):
pythonic_dict = dict()
json_syntax_dict = json_method(json_string, **kwargs)
if not convert_syntax:
return json_syntax_dict
for key, value in json_syntax_dict.iteritems():
for json_syntax in re.finditer(r'[A-Z]', key):
key = key.replace(
json_syntax.group(), '_' + json_syntax.group()[0].lower())
pythonic_dict[key] = value
return pythonic_dict
return wrapper
My concern with this method is that it this monkeys with the expected order of keyword parameters in json.loads (It makes convert_syntax the first expected parameter after the json string) and could mess up other calls to json.loads within the larger program that assume the standard order.
Seeing as your change breaks the expected signature of json.loads and you're concerned with it breaking other code that depends on the original signature, I'd agree with Simeon Visser, seems like you shouldn't do this at all.
Only code you write will be able to properly call your new method, so why not give your method a different name, rather than decorating an existing method? If you want to prevent other code from calling this method without the convert_syntax flag, just avoid importing the json module at all, and instead import your json library that wraps the json module.
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)
i have see some code like bellow:
params = {
'username': username,
'password': password,
'attended': attended,
'openid_identifier': openid_identifier,
'multistage': (stage and True) or None
}
ret = authmethod.login(request, userobj, **params)
login is implemented like this
def login(self,request,user_obj,**kw):
username = kw.get('username')
password = kw.get('password')
so we know that kw is a dictionary , but i don't know the ** meaning , is it something like pointer in C language ? is it used to input the dictionary as a reference .
thank you if you could answer me .
Basically this is what it means:
Without using **kw, you would need to list all the input parameters for login in it's signature.
Now, you are calling login function and you know what variable names login's parameters are. So if you have a lot of parameters, it's difficult to always remember the order of the parameters.
Therefore, you call login on parameters by naming the parameters' variable names and setting them equal to the value that you want to pass it. Think of it like this:
Without using **kw, you'd do this:
def say(phrase):
print phrase
say("Hello, World!")
But, by using **kw, you can do this:
def say(**kw):
phrase = kw.get('say_what')
print phrase
say(**{'say_what':"Hello, World!"})
Now what happens is that using ** "unpacks the dictionary in such a way that it tells say that what it expects as the input parameter named say_what will have the value "Hello, World!".
The above example is not the best place to use **kw because there is only one input parameter. But if you have a function with a long signature, then it would be unreasonable to expect any programmer to remember exactly what parameters must be passed in what order to this function.
If (you and) the programmer were to use **kw, then the programmer can specify a dictionary which maps input the parameters' variable names (as strings) to their values. The function takes care of the rest and the programmer doesn't have to concern himself with the order in which he passes the parameters to the function
Hope this helps
These are called keyword arguments and they're described in lots of places, like the Python manual and in blog posts.