I am trying to create a 'general' function for multiple uses with different amounts of keys and cds, what is a way to do it? How can I state how many keys(and, therefore, cds) I am going to need in the function? Thank you!
def get_keyboard(key1, cd1, key2, cd2,key3, cd3):
cb_data1 = menu_cb.new(subsection=cd1)
cb_data2 = menu_cb.new(subsection=cd2)
cb_data3 = menu_cb.new(subsection=cd3)
inline_button1 = types.InlineKeyboardButton(key1,callback_data=cb_dat1)
inline_button2 = types.InlineKeyboardButton(key2,callback_data=cb_dat2)
inline_button3 = types.InlineKeyboardButton(key3,callback_data=cb_dat3)
return types.
InlineKeyboardMarkup(row_width=3).
row(inline_button1,inline_button2, inline_button3)
This does what was asked for:
def get_keyboard(*args):
inline_buttons = []
for key, cd in zip(args[::2], args[1::2]):
cb_data = menu_cb.new(subsection=cd)
inline_button = types.InlineKeyboardButton(key, callback_data=cb_data)
inline_buttons.append(inline_button)
return (
types
.InlineKeyboardMarkup(row_width=len(inline_buttons))
.row(*inline_buttons)
)
But this might be a better function signature:
def get_keyboard(key_cd_pairs):
for key, cd in key_cd_pairs:
...
Or even the simple:
def get_keyboard(keys, cds):
for key, cd in zip(keys, cds):
...
Related
Hi can someone please help me in reducing the complexity of the below mentioned code as I am new to this I need it to reduce the amount of code and improve the code and to improve simplicity and reduce duplications in the overall coding any any help in this regard can be of great help and thanks in advance for your time and consideration in helping me in this regard.
def update(self, instance, validated_data):
instance.email_id = validated_data.get('email_id', instance.email_id)
instance.email_ml_recommendation = validated_data.get('email_ml_recommendation',
instance.email_ml_recommendation)
instance.ef_insured_name = validated_data.get('ef_insured_name', instance.ef_insured_name)
instance.ef_broker_name = validated_data.get('ef_broker_name', instance.ef_broker_name)
instance.ef_obligor_name = validated_data.get('ef_obligor_name', instance.ef_obligor_name)
instance.ef_guarantor_third_party = validated_data.get('ef_guarantor_third_party',
instance.ef_guarantor_third_party)
instance.ef_coverage = validated_data.get('ef_coverage', instance.ef_coverage)
instance.ef_financials = validated_data.get('ef_financials', instance.ef_financials)
instance.ef_commercial_brokerage = validated_data.get('ef_commercial_brokerage',
instance.ef_commercial_brokerage)
# fixing bug of pipeline
instance.ef_underwriter_decision = validated_data.get('ef_underwriter_decision',
instance.ef_underwriter_decision)
instance.ef_decision_nty_fields = validated_data.get('ef_decision_nty_fields',
instance.ef_decision_nty_fields)
instance.ef_feedback = validated_data.get('ef_feedback', instance.ef_feedback)
instance.relation_id = validated_data.get('relation_id', instance.relation_id)
instance.email_outlook_date = validated_data.get('email_outlook_date',
instance.email_outlook_date)
instance.ef_decision_nty_fields = validated_data.get('ef_decision_nty_fields',
instance.ef_decision_nty_fields)
instance.ef_pl_est_premium_income = validated_data.get('ef_pl_est_premium_income',
instance.ef_pl_est_premium_income)
instance.ef_pl_prob_closing = validated_data.get('ef_pl_prob_closing',
instance.ef_pl_prob_closing)
instance.ef_pl_time_line = validated_data.get('ef_pl_time_line', instance.ef_pl_time_line)
instance.ef_pipeline = validated_data.get('ef_pipeline', instance.ef_pipeline)
instance.el_insured_margin = validated_data.get('el_insured_margin', instance.el_insured_margin)
instance.ef_last_updated = validated_data.get('ef_last_updated', instance.ef_last_updated)
instance.relation_id = validated_data.get('relation_id', instance.relation_id)
# CR3.2 Primium and basis point addition
instance.broker_email_id = validated_data.get('broker_email_id', instance.broker_email_id)
instance.premium = validated_data.get('premium', instance.premium)
instance.basis_points = validated_data.get('basis_points', instance.basis_points)
instance.basis_points_decision = validated_data.get('basis_points_decision',
instance.basis_points_decision)
embedded_json = validated_data.get('email_embedd', instance.email_embedd)
instance.email_embedd = json.dumps(embedded_json)
If all items in your dictionary validated_data that have a corresponding attribute in instance have to be copied to that instance, then iterate those items and use setattr to set the corresponding attributes of your instance object.
You seem to have one special case where a value needs to be stringified as JSON. So you'll need specific code to deal with that scenario:
def update(self, instance, validated_data):
for key, value in validated_data.items():
if hasattr(instance, key):
if key == "email_embedd": # special case
instance.email_embedd = json.dumps(value)
else:
setattr(instance, key, value)
A Logical Error...
There is a problem in your code for the special case:
embedded_json = validated_data.get('email_embedd', instance.email_embedd)
instance.email_embedd = json.dumps(embedded_json)
If this gets executed when validated_data does not have the key email_embedd, then embedded_json will default to instance.email_embedd. But that value is already JSON encoded! So if you now proceed with json.dumps(embedded_json) you'll end up with a JSON string that itself has been stringified again!
This problem will not occur with the code proposed above.
I'm trying to figure it out a way to create a namedtuple with variable fields depending on the data you receive, in my case, I'm using the data from StatCounter and not on all the periods are the same browsers. I tried this way but it is a bit ugly and I'm sure there is a better way to achieve it.
def namedtuple_fixed(name: str, fields: List[str]) -> namedtuple:
"""Check the fields of the namedtuple and changes the invalid ones."""
fields_fixed: List[str] = []
for field in fields:
field = field.replace(" ", "_")
if field[0].isdigit():
field = f"n{field}"
fields_fixed.append(field)
return namedtuple(name, fields_fixed)
Records: namedtuple = namedtuple("empty_namedtuple", "")
def read_file(file: str) -> List["Records"]:
"""
Read the file with info about the percentage of use of various browsers
"""
global Records
with open(file, encoding="UTF-8") as browsers_file:
reader: Iterator[List[str]] = csv.reader(browsers_file)
field_names: List[str] = next(reader)
Records = namedtuple_fixed("Record", field_names)
result: List[Records] = [
Records(
*[
dt.datetime.strptime(n, "%Y-%m").date()
if record.index(n) == 0
else float(n)
for n in record
]
)
for record in reader
]
return result
The "namedtuple_fixed" function is to fix the names that have invalid identifiers.
Basically, I want to create a named tuple that receives a variable number of parameters, depending on the file you want to analyze. And if it's with type checking incorporated (I mean using NamedTuple from the typing module), much better.
Thanks in advance.
This solves my problem, but just partially
class Record(SimpleNamespace):
def __repr__(self):
items = [f"{key}={value!r}" for key, value in self.__dict__.items()]
return f"Record({', '.join(items)})"
Using the types.SimpleSpace documentation
And it can cause problems, like for example if you initiallize a Record like the following:
foo = Record(**{"a": 1, "3a": 2})
print(foo.a) # Ok
print(foo.3a) # Syntax Error
Is there a way I can create named variables in the local scope from a json file?
document json
This is my json file, I would like to create variables in the local scope named as the path of my json dictionary
This is how I manually create them, I would like to do it automatically for all the json file. Is it possible?
class board(object):
def __init__(self, json, image):
self.json = json
self.image = image
def extract_json(self, *args):
with open(self.json) as data_file:
data = json.load(data_file)
jsonpath_expr = parse(".".join(args))
return jsonpath_expr.find(data)[0].value
MyAgonism = board('document.json', './tabellone.jpg')
boxes_time_minutes_coord = MyAgonism.extract_json("boxes", "time_minutes", "coord")
boxes_time_seconds_coord = MyAgonism.extract_json("boxes", "time_seconds", "coord")
boxes_score_home_coord = MyAgonism.extract_json("boxes", "score_home", "coord")
I think you're making this much more complicated than it needs to be.
with open('document.json') as f:
d = json.load(f)
time_minutes_coords = d['boxes']['time_minutes']['coord']
time_seconds_coords = d['boxes']['time_seconds']['coord']
score_home_coords = d['boxes']['score_home']['coord']
If you actually want to create named variables in the local scope from the keys in your json file, you can use the locals() dictionary (but this is a terrible idea, it's far better just to reference them from the json dictionary).
# Flatten the dictionary keys.
# This turns ['boxes']['time_minutes']['coord']
# into "boxes_time_minutes_coord"
def flatten_dict(d, k_pre=None, delim='_', fd=None):
if fd is None:
fd = {}
for k, v in d.iteritems():
if k_pre is not None:
k = '{0}{1}{2}'.format(k_pre, delim, k)
if isinstance(v, dict):
flatten_dict(v, k, delim, fd)
else:
fd[k] = v
return fd
fd = flatten_dict(d)
locals().update(fd)
print boxes_time_minutes_coord
Lots of caveats, like the possibility of overwriting some other variable in your local scope, or the possibility that two dictionary keys could be identical after flattening unless you choose a delimiter that doesn't appear in any of the dictionary keys. Or that this won't work if your keys contain invalid characters for variable names (like spaces for example).
I need a container in python which I can access like/or similar to this:
map = buildMap()
versionA = map['A'].version
osA = map['A'].os
versionB = map['B'].version
osB = map['B'].os
Anything like this in python (from 2.7 and down)?
You can create a class and a dictionary, where you can map the instances of the class with key strings, like this
class OSMap(object):
def __init__(self, os = "", version = ""):
self.os = os
self.version = version
os_map = dict()
os_map["A"] = OSMap("Windows", "7")
os_map["B"] = OSMap("Ubuntu", "13.10")
print os_map["A"].version, os_map["A"].os
print os_map["B"].version, os_map["B"].os
Output
7 Windows
13.10 Ubuntu
Alternatively, you can use collections.namedtuple, like this
from collections import namedtuple
OSMap = namedtuple("OSMap", ("os", "version"))
os_map = dict()
os_map["A"] = OSMap("Windows", "7")
os_map["B"] = OSMap("Ubuntu", "13.10")
print os_map["A"].version, os_map["A"].os
print os_map["B"].version, os_map["B"].os
Note: namedtuple objects cannot be changed later, as they are derived from tuple.
Well you have dict that does what you are looking for.
my_map = dict()
my_map['A'] = {'os': 'osa'}
my_map['B'] = {'os': 'osb'}
It is a dictionary whose values are dictionaries themselves.
I'm looking for ways to write functions like get_profile(js) but without all the ugly try/excepts.
Each assignment is in a try/except because occasionally the json field doesn't exist. I'd be happy with an elegant solution which defaulted everything to None even though I'm setting some defaults to [] and such, if doing so would make the overall code much nicer.
def get_profile(js):
""" given a json object, return a dict of a subset of the data.
what are some cleaner/terser ways to implement this?
There will be many other get_foo(js), get_bar(js) functions which
need to do the same general type of thing.
"""
d = {}
try:
d['links'] = js['entry']['gd$feedLink']
except:
d['links'] = []
try:
d['statisitcs'] = js['entry']['yt$statistics']
except:
d['statistics'] = {}
try:
d['published'] = js['entry']['published']['$t']
except:
d['published'] = ''
try:
d['updated'] = js['entry']['updated']['$t']
except:
d['updated'] = ''
try:
d['age'] = js['entry']['yt$age']['$t']
except:
d['age'] = 0
try:
d['name'] = js['entry']['author'][0]['name']['$t']
except:
d['name'] = ''
return d
Replace each of your try catch blocks with chained calls to the dictionary get(key [,default]) method. All calls to get before the last call in the chain should have a default value of {} (empty dictionary) so that the later calls can be called on a valid object, Only the last call in the chain should have the default value for the key that you are trying to look up.
See the python documentation for dictionairies http://docs.python.org/library/stdtypes.html#mapping-types-dict
For example:
d['links'] = js.get('entry', {}).get('gd$feedLink', [])
d['published'] = js.get('entry', {}).get('published',{}).get('$t', '')
Use get(key[, default]) method of dictionaries
Code generate this boilerplate code and save yourself even more trouble.
Try something like...
import time
def get_profile(js):
def cas(prev, el):
if hasattr(prev, "get") and prev:
return prev.get(el, prev)
return prev
def getget(default, *elements):
return reduce(cas, elements[1:], js.get(elements[0], default))
d = {}
d['links'] = getget([], 'entry', 'gd$feedLink')
d['statistics'] = getget({}, 'entry', 'yt$statistics')
d['published'] = getget('', 'entry', 'published', '$t')
d['updated'] = getget('', 'entry', 'updated', '$t')
d['age'] = getget(0, 'entry', 'yt$age', '$t')
d['name'] = getget('', 'entry', 'author', 0, 'name' '$t')
return d
print get_profile({
'entry':{
'gd$feedLink':range(4),
'yt$statistics':{'foo':1, 'bar':2},
'published':{
"$t":time.strftime("%x %X"),
},
'updated':{
"$t":time.strftime("%x %X"),
},
'yt$age':{
"$t":"infinity years",
},
'author':{0:{'name':{'$t':"I am a cow"}}},
}
})
It's kind of a leap of faith for me to assume that you've got a dictionary with a key of 0 instead of a list but... You get the idea.
You need to familiarise yourself with dictionary methods Check here for how to handle what you're asking.
Two possible solutions come to mind, without knowing more about how your data is structured:
if k in js['entry']:
something = js['entry'][k]
(though this solution wouldn't really get rid of your redundancy problem, it is more concise than a ton of try/excepts)
or
js['entry'].get(k, []) # or (k, None) depending on what you want to do
A much shorter version is just something like...
for k,v in js['entry']:
d[k] = v
But again, more would have to be said about your data.