Taking Advantage of *args and **kwargs
I consistently forget the option word I have included in a function and so I had to design a way to accept different keywords (option) names to trigger features with in a function.
As an example, assigning a color to a box border is very easy by just adding something like this to a function’s arguments:
def buildabox(msg, border_color="red"):
"""
docs go here to put a box around msg
"""
...
But, if you accidenally call the function like this, it will fail. my_box = buildabox(“my message”, box_color=“white on back”): …
Or maybe you used this and it will fail again.. my_box = buildabox(“my message”, box_clr=“white on back”): …
So there is a way to deal with all of those possibilities using **kwargs and using the function kvarg_val() listed here below.
So instead of declaring each key-value pair we can do this:
def buildabox(msg, **kwargs):
"""
docs go here to put a box around msg
"""
box_clr = kvarg_val(["border_color", "border_clr", 'box_color', "box_clr"], kwargs, dflt="red")
# now, if any key is used that is in that list box_clr reflect the value provided
# and if none is provided then the default assignment of "red"
...
Now, what about a boolean value where you use a similar key word but not the stipulated var name. For example:
def buildabox(msg, display=False, **kwargs):
"""
docs go here to put a box around msg
options:
- display: bool
returns lines suitable for printing the returned box
"""
box_clr = kvarg_val(["border_color", "border_clr", 'box_color', "box_clr"], kwargs, dflt="red")
...
returns lines
If I call this function like this it will fail:
lines = buildabox("my message", 'print', box_clr="white"):
Unless I take advantage of *args and use the bool_val function below… like this
def buildabox(msg, *args, **kwargs):
"""
docs go here to put a box around msg
options:
- display: bool
returns lines suitable for printing the returned box
"""
box_clr = kvarg_val(["border_color", "border_clr", 'box_color', "box_clr"], kwargs, dflt="red")
display = bool_val(["display", "print", "prnt", "show"], args, kwargs, dflt=False)
# Now this call will work:
# buildabox(msg, 'show', box_color="yellow! on black") # or any key-name listed
...
returns lines
There are probably better ways to do this but this works for me.
# #######################################
def kvarg_val(key, kwargs_d={}, *args, **kwargs):
# ###################################
"""
purpose: returns a value when the key in a key=value pair matches any key given
NOTE: key can be a string or a list of strings
option: dflt="Whatever default value you want"
use: used in function to get a value from a kwargs ky=value pair
- eg:
def my_function(*args, **kwargs):
txt_center = kvarg_val(["text_center", "txt_cntr", "txtcntr"], kwargs, dflt=1)
- so if you call my_function(txt_center=99) then txt_center will be set to 99
---
If any key in the list is set = to a value, that value is returned
see: bool_val which process both args and kvargs and returns bool_val
input key(string), kvargs_d(dictionary of key,vals), default(string; optional)
purpose: return a value given by a key=value pair using a matching key (in key list if desired)
options:
- key provided can be a string or a list of strings
- dflt="Whatever default value you want - can be a string, list, int, float... whatever" <-- this is optional, if not declared "" is returned
if key in kvargs:
return val
else:
return default
returns str(key_val) or default_val(which is "" if none is provided)
"""
"""--== Init ==--"""
required = False
if "required" in args:
required = True
if 'required' in list(kwargs.keys()):
required = True
mydflt = ""
if 'dflt' in kwargs:
mydflt = kwargs['dflt']
"""--== Validate ==--"""
if required:
found_flag = False
for my_k in kwargs_d.keys():
if my_k in key:
found_flag = True
if not found_flag:
dbug(f"A value for a key: {key} is required for this operation.", 'ask', 'boxed')
"""--== Init ==--"""
my_val = mydflt
if not isinstance(kwargs_d, dict):
dbug(f"Supplied kwargs_d: {kwargs_d} MUST be a dictionary! Returning...")
return
"""--== Convert ==--"""
if isinstance(key, list):
keys = key
else:
keys = [key]
"""--== Process ==--"""
for k in keys:
if k in kwargs_d:
my_val = kwargs_d[k]
if my_val == "False":
my_val = False
if my_val == "True":
my_val = True
return my_val
# ### EOB def kvarg_val(key, kwargs_d={}): ### #
def bool_val(key_l, args_l, kvargs={}, **kwargs):
# #######################################
"""
purpose: look at args and kwargs with a list of possible option strings and return the default True or False
requires:
- key_l: str | list # this is the string or list of strings to check args and kwargs against
options:
- default | dflt: bool # the default value to return
- opposite | opposites: str | list # a list of opposites
eg: prnt = bool_val(["print", "prnt"], args, kwargs, dflt=True, opposites=['noprnt', 'no_prnt', 'no_print'])
return True or False
Notes:
key_l can be a str or list
args_l must be provided
kvargs is optional
used to see if a string or a list of stings might be declared true
by being in args or seeing it has a bool value set in kvargs
use:
DBUG = bool_val('dbug', args, kvargs)
or
DBUG = bool_val(['dbug', 'DBUG'], args, kvargs)
"""
"""–== Config ==–"""
bool_v = kvarg_val(["default", "dflt"], kwargs, dflt=False)
opposite_words = kvarg_val(['opposite', 'opposites'], kwargs, dflt=[])
"""–== Validate ==–"""
if not isinstance(opposite_words, list) and opposite_words != []:
opposite_words = [opposite_words]
"""–== Convert ==–"""
if isinstance(key_l, str):
key_l = [key_l] # make it a list
for k, val in kvargs.items():
if kvargs[k] == "False":
kvargs[k] = False
if kvargs[k] == "True":
kvargs[k] = True
"""–== Init ==–"""
opposite_b = False
"""–== Process ==–"""
for key in key_l:
if key in args_l:
bool_v = True
if key in kvargs:
bool_v = kvargs[key]
for word in opposite_words:
if word in args_l:
opposite_b = True
if word in kvargs:
# convert strings to boolean when needed
if kvargs[word] == "False":
kvargs[word] = False
if kvargs[word] == "True":
kvargs[word] = True
if isinstance(kvargs[word], bool):
opposite_b = kvargs[word]
if opposite_b:
bool_v = False
return bool_v
Enjoy!
comments powered by Disqus