How to save results from a loop separately? - python

I need my results to be saved separately so that I can run the rest of my code.
Basically, I have to do a project on loans and each type of loan would have a different monthly repayment amount. The problem now is that each user might have a different number of different loans. For example, one user might only have home loan (HL) while one user might have 3 different loans. In my codes, I need to include this which would return the monthly repayment amount for that particular type of loan:
def meet_criteria(account_no):
if getsaving(account_no) in ["HL"]:
HLmonthly()
else:
if getsaving(account_no) in ["RL"]:
RLmonthly()
else:
if getsaving(account_no) in ["EL"]:
ELmonthly()
I also need to sum up the repayment amount like this:
total_monthly_debt = repay1 + repay2 + repay3
However, right now, I can't to proceed with above codes as I am unable to separate the results to get the 'HL', 'RL' and 'EL' that I need to call the meet criteria(). In order to get all the results to show, I am using a loop like so:
def getsaving(account_no):
query = """\
select SUBSTRING(LoanID, 1, 2)
from Account_Delinquency
where Account_Number = '{}'
""" .format(account_no)
return (execute_read_query (conn, query))
a = getsaving(account_no)
mylist = []
for i in a:
mylist.append(i)
I tried to put it in a list so that I could separate it but obviously, it doesn't work that way. This was a method I learnt to check if a list is empty but as expected, it can't check if parts of the list is empty and would return error. It also involves a little hardcoding which is not ideal.
if mylist[1][0]:
loan1 = mylist[1][0]
else:
pass
Hence, I am asking to see if there are any other methods I can use so that I can get a result of, for example, Loan1 = HL, Loan2 = nothing, Loan3 = RL etc. I would also appreciate any suggestions for changes to my code as I know it is not the most ideal. Thank you!

meet_criteria seems incorect (no return value)
def meet_criteria(account_no):
if getsaving(account_no) in ["HL"]:
HLmonthly()
else:
if getsaving(account_no) in ["RL"]:
RLmonthly()
else:
if getsaving(account_no) in ["EL"]:
ELmonthly()
could be
def meet_criteria(account_no):
if getsaving(account_no) == "HL":
HLmonthly()
elif getsaving(account_no) == "RL":
RLmonthly()
elif getsaving(account_no) == "EL":
ELmonthly()
Btw. I haven't fully understood your question, but I think that you want meet_criteria to return something, (I would know for sure if you provided how you use this function).
So instead do
def meet_criteria(account_no):
if getsaving(account_no) == "HL":
return HLmonthly()
elif getsaving(account_no) == "RL":
return RLmonthly()
elif getsaving(account_no) == "EL":
return ELmonthly()
Further improvements:
if mylist[1][0]:
loan1 = mylist[1][0]
else:
pass
The else branch doesn't do anything. Also, if you haven't defined loan1 before and you are using it later, you would get NameError: name 'loan1' is not defined.
To remove else branch:
if mylist[1][0]:
loan1 = mylist[1][0]
To not get NameError
if mylist[1][0]:
loan1 = mylist[1][0]
else:
loan1 = 0 # if it is suposed to be integer, maybe you want None of False

Related

Is there an alternative to .endswith()?

I am trying to write an if, elif else clause, so that depending on the German word ending, we can see is it should go with der, die or das.
Here is my code:
word = input ("Enter word: ")
if (word.endswith('er' 'ismus')):
print ("der")
elif (word.endswith('falt' 'heit' 'keit' 'schaft' 'ung')):
print ("die")
else (word.endswith('chen' 'lein')):
print ("das")
I have also tried using suffix with square brackets but everything goes grey when I do that and so I can assume it won't work. And clearly true and false are not adequate responses for what I need. Is there anything else I can try?
Thanks in advance!
The endswith method really only checks if the word ends with one thing, but you can do something like:
def word_ends_with_one_of(word, options):
for option in options:
if word.endswith(option):
return True
return False
Then call that with:
suffix_die = ['falt', 'heit', 'keit', 'schaft', 'ung']
suffix_der = ['er', 'ismus']
suffix_das = ['chen', 'lein']
if word_ends_with_one_of(word, suffix_die):
print ("die")
elif word_ends_with_one_of(word, suffix_der):
print ("der")
elif word_ends_with_one_of(word, suffix_das):
print ("das")
As an aside, your else clause is currently problematic, it should not have a condition attached to it (unless it's a typo and you meant to have an elif instead).
Now, even though that you be a useful function to have for other purposes, you may want to consider a more application focused method since you'll be introducing a function anyway. By that, I mean something more closely suited to your specific needs, such as:
def definite_article_for(word):
# Could also use word_ends_with_one_of() in here.
if word.endswith('er'): return 'der'
if word.endswith('ismus'): return 'der'
if word.endswith('falt'): return 'die'
:
if word.endswith('lein'): return 'das'
return None
}
Then use article = definite_article_for(my_word) to get the article you want.

Turning a list number, into another value that is returned [python]

I am currently working on this code:
def N_C(question,choice):
N_C_choice_count_max = len(choice)
N_C_choice_count_min = N_C_choice_count_max - N_C_choice_count_max
N_C_restart_input = True
N_C_choices = []
print(question)
for i in range (N_C_choice_count_min,N_C_choice_count_max):
print(N_C_choice_count_min+i+1,":",choice[i])
str(N_C_choices.append(N_C_choice_count_min+i+1))
while N_C_restart_input == True:
N_C_input = input(">")
if str(N_C_input) in str(N_C_choices):
break
else:
continue
return(N_C_input)
N_C("question",["choice1","choice2","asmanychoicesasyouwant"])
And it works fine as it is, but to select a choice you input the number of the choice, which makes sense, but I would like for it to instead return the number they choose, the actual choice that goes with that number.
I am thinking that maybe something with a dictionary could work, or even just using the choice list provided, but I cannot figure it out, and help is appreciated.
choice is a list containing all the answers and N_C_input is a number as a string, which is associated to choice.
return choice[int(N_C_input)-1]
Returns the actual choice.

Match multiple keys values to database entry in TinyDB?

I am having a hard time finding out if I can check multiple key values at once with TinyDB. Currently I can check multiple fields by using and in an if statement like this:
def check_table(FNAME="NULL", LNAME="NULL", MNAME="NULL"):
if (HHK_STAFF.search(Query().FNAME == FNAME)) != [] \
and (HHK_STAFF.search(Query().MNAME == MNAME)) != [] \
and (HHK_STAFF.search(Query().LNAME == LNAME)) != []:
print(HHK_STAFF.search(Query().FNAME == FNAME)[0])
else:
print("user does not exist")
check_table(FNAME="Some", MNAME="Random", LNAME="Person")
It does what I want however it seams bulky. I am hoping there is something built into TinyDB that can perform the same function without the need for many and statements.
I am trying to do something akin to:
HHK_STAFF.search(where(("FNAME", "MNAME", "LNAME")) == (FNAME, MNAME, LNAME)))
Question:
Is anyone aware of a way to Query() the table for multiple key values instead of just one at a time?
Can you list a link to this information? I have had a hard time locating this bit of info if it exist.
Here is a simple version of what I am ding with TinyDB:
from tinydb import TinyDB, Query
#~~~~~~~~~~~~~~~~~~~~~~< CURRENT DBPATH >~~~~~~~~~~~~~~~~~~~~~~
DB = TinyDB('./DB_PATH/HHK_DB.json')
#~~~~~~~~~~~~~~~~~~~~~~< CURRENT TABLES >~~~~~~~~~~~~~~~~~~~~~~
HHK_STAFF = DB.table("HHK_STAFF")
HHK_STAFF.insert({'EMPLOYEE_ID':'00000001', 'FNAME': 'Some', 'LNAME':'Person', 'MNAME':'Random'})
def check_table(FNAME="NULL", LNAME="NULL", MNAME="NULL"):
if (HHK_STAFF.search(Query().FNAME == FNAME)) != [] \
and (HHK_STAFF.search(Query().MNAME == MNAME)) != [] \
and (HHK_STAFF.search(Query().LNAME == LNAME)) != []:
print(HHK_STAFF.search(Query().FNAME == FNAME)[0])
else:
print("user does not exist")
check_table(FNAME="Some", MNAME="Random", LNAME="Person")
Results:
{'EMPLOYEE_ID': '00000001', 'FNAME': 'Some', 'LNAME': 'Person', 'MNAME': 'Random'}
According to Advanced Usage — TinyDB 3.8.1.post1 documentation, a logical AND would look like this:
q = Query()
HHK_STAFF.search((q.FNAME == FNAME) & (q.MNAME == MNAME) & (q.LNAME == LNAME))
According to git blame of tinydb/queries.py, it's been available always, since the very first release.
You can use the python builtin all to achieve a shorter, more flexible work-alike to your sample code:
def check_table2(**query):
if all(HHK_STAFF.search(getattr(Query(), k) == v)
for k, v in query.items()):
print(HHK_STAFF.search(Query().FNAME == query['FNAME'])[0])
else:
print("user does not exist")
But you should be sure this is actually what you want. The English equivalent would be,
"If someone with this last name exists, and someone with this first
name exists, and someone with this middle name exists, regardless of
whether they're all the same someone, return the person with the matching first name."
In other words, If I now add another person to your database
HHK_STAFF.insert({'EMPLOYEE_ID':'00000002',
'FNAME': 'Anne',
'LNAME':'Person',
'MNAME':'Other'})
Your function above will return something for the query
check_table(FNAME="Some", MNAME="Other", LNAME="Person")
Even though Some's middle name is "Random" not "Other", just because somebody else exists on the system whose middle name is "Other"
You may instead want to take advantage of Query's overridden __and__ operator to find a single person that has all the names you're querying:
q = Query()
HHK_STAFF.search((q.FNAME=="Anne") &
(q.MNAME=="Other") &
(q.LNAME=="Person"))
Or, for something using key-value like I did above, using functools.reduce:
from functools import reduce
def user_matching_all(**query):
q = Query()
out = HHK_STAFF.search(reduce(lambda x, y: x & y,
[getattr(q, k) == v
for k, v in query.items()]))
if out:
print(out)
else:
print("user does not exist")

GET Request Flask

I have written something that works, but I am 100% sure that there is an even more efficient and faster way of doing what I did.
The code that I have written, essentially uses OpenBayes' library and creates a network with its nodes, relationships between nodes, and the probabilities and distributions associated with each of the nodes. Now, I was creating a GET request using Flask, in order to process the conditional probabilities by simply sending the request.
I will send some evidence (given values), and set the node in which I want its probability (observed value). Mathematically it looks like this:
Observed Value = O and Evidence = En, where n > 1
P( O | E1, E2, ..., En)
My final goal would be to have a client/server ping the server hosting this code(with the right parameters) and constantly give me the final values of the observed probability, given the evidence (which could be 1 or more values). The code I have written so far for the GET request portion is:
#app.route('/evidence/evidence=<evidence>&observed=<obv>', methods=['GET'])
def get_evidence(evidence, obv):
# Take <evidence> and <obv> split them up. For example:
# 'cloudy1rain0sprinkler1' to 'cloudy1', 'rain0' and 'sprinkler1', all in a nice list.
analyzeEvidence, observedNode = evidence.upper().strip(), obv.upper().strip()
string, count, newCount, listOfEvidence = "", 0, 0, {}
counter = sum(character.isdigit() for character in analyzeEvidence)
# This portion is to set up all the evidences.
for y in xrange(0, counter):
string, newCount = "", count
for x in xrange(newCount, len(analyzeEvidence)):
count += 1
if analyzeEvidence[x].isalpha() == True:
string += str(analyzeEvidence[x])
elif analyzeEvidence[x].isdigit() == True and string in allNodes:
if int(analyzeEvidence[x]) == 1 or int(analyzeEvidence[x]) == 0:
listOfEvidence[string] = int(analyzeEvidence[x])
break
else: abort(400)
break
else: abort(400)
net.SetObs(listOfEvidence) # This would set the evidence like this: {"CLOUDY": 1, "RAIN":0}
# This portion is to set up one single observed value
string = ""
for x in xrange(0, len(observedNode)):
if observedNode[x].isalpha() == True:
string += str(observedNode[x])
if string == "WETGRASS":
string = "WET GRASS"
elif observedNode[x].isdigit() == True and string in allNodes:
if int(observedNode[x]) == 1 or int(observedNode[x]) == 0:
observedValue = int(observedNode[x])
observedNode = string
break
else: abort(400)
else: abort(400)
return str(net.Marginalise(observedNode)[observedValue]) # Output returned is the value like: 0.7452
Given my code, is there any way to optimize it? Also, Is there a better way of passing these parameters that doesn't take so many lines like my code does? I was planning on setting fixed key parameters, but because my number of evidence can change per request, I thought this would be one way in doing so.
You can easily split your evidence input into a list of strings with this:
import re
# 'cloudy1rain0sprinkler1' => ['cloudy1', 'rain0' and 'sprinkler1'].
evidence_dict = {}
input_evidence = 'cloudy1rain0sprinkler1'
# looks for a sequence of alphabets followed by any number of digits
evidence_list = re.findall('([a-z]+\d+)', input_evidence.lower())
for evidence in evidence_list:
name, val, _ = re.split('(\d+)', evidence)
if name in allNodes:
evidence_dict[name] = val
# evidence_dict = {'cloudy': 1, 'rain': 0, 'sprinkler': 1}
You should be able to do something similar with the observations.
I would suggest you use an HTTP POST. That way you can send a JSON object which will already have the separation of variable names and values done for you, all you'll have to do is check that the variable names sent are valid in allNodes. It will also allow your variable list to grow somewhat arbitrarily.

Python: Multiple instances seem to be sharing properties (or something?!)

Python is my first language, and I am very new to it, so the answer may be very clear, but after many hours looking and experimenting, I am not sure what is causing the problem.
An overview of the module:
The DicePool module is meant to manage collections of "dice", stored as dictionary items. Each dictionary key (herein poolKey) has a list containing information about one "type" of dice, most importantly, a tuple describing its faces and an integer representing the quantity of "dice" type 'x' in the "pool."
My specific question regards the Transfer method, which used to be two methods (send and receive, basically), but which I thought I could combine into one method. When the test code at the bottom runs, I'd like it to leave dp.dictPool[poolKey][1] == 0 and dp2.dictPool[poolKey][1] == 2. But in every attempt I've made, the values come out the same. Sorry I can't categorize this question better . . . I don't really know what the problem is.
Anyway, one half of the Transfer method is supposed to run for the "sender" instance, and one half is supposed to run for the "receiver" instance.
import random
class DicePool(object):
def __init__(self):
self.dictPool = {}
def AddDice(self, poolKey, faces = 6, quant = 1, color = "white"):
'''faces must be int or items 'a,b,c'; count must be int or def to 1'''
try: #if count is not an integer, it defaults to 1
quant = int(quant)
except:
print("Quant is not an integer, defaulting to 1")
quant = 1
try: #if faces is can be int, a list is built of numbers 1 to faces
faces = int(faces)
if faces < 2: #a 1 or 0-sided die breaks the program
faces = 2
tempList = []
for i in range(1, faces+1):
tempList.append(i)
faces = tempList
except: #if faces is not an integer, it is split into list items by ","
faces = faces.split(",")
if poolKey in self.dictPool.keys(): #if the key already exists in pool
self.dictPool[poolKey][1] += quant #add to the quantity,
else: #if the key does not already exist, set all attributes
self.dictPool[poolKey] = [faces, quant, color]
def Transfer(self, poolKey, targetPool, sendQuant, senderPool = None):
'''targetPool must be DicePool instance'''
if targetPool:
self.dictPool[poolKey][1] -= sendQuant
targetPool.Transfer(poolKey, None, sendQuant, self)
else:
try:
self.dictPool[poolKey][1] -= sendQuant
except:
self.dictPool[poolKey] = senderPool.dictPool[poolKey]
self.dictPool[poolKey][1] = sendQuant
dp = DicePool()
dp2 = DicePool()
dp.AddDice("d6")
dp.AddDice("d6")
dp.Transfer("d6",dp2,2)
print(dp.dictPool,dp2.dictPool)
The problem is in this line:
self.dictPool[poolKey] = senderPool.dictPool[poolKey]
The values in your dictPools are lists. Here, you set one object's dictPool value to the same list as in the other one. Not a copy of the list, but the same list. So later if you add or subtract from that list, it will affect the other as well, because they are sharing one list object.
Try doing self.dictPool[poolKey] = senderPool.dictPool[poolKey][:]. The [:] grabs the contents of the list rather than the list object iself.
In both parts of the if/else in Transfer you're subtracting the quantity. Don't you want to subtract it in one case but add it in the other?
Is else: try: self.dictPool[poolKey][1] -= sendQuant supposed to be += sendQuant instead?
Might be a semantic issue, not a Python syntax issue.
Here is a version of the Transfer() method that seems to work as intended (more or less), although it's very clumsy looking:
def Transfer(self, poolKey, targetPool, sendQuant, senderPool = None):
'''targetPool must be DicePool instance'''
if isinstance(targetPool, DicePool):
#valid target, so subtract dice here, then call Transfer on target
temp = self.dictPool[poolKey][1:2][0] - sendQuant
print("sent",sendQuant,"leaving",temp)
targetPool.Transfer(poolKey, "Receiver", sendQuant, self)
elif targetPool == "Receiver":
#this executes if a DicePool is named as the targetPool of Transfer
if poolKey in self.dictPool.keys():
self.dictPool[poolKey][1:2][0] += sendQuant
else:
self.dictPool[poolKey] = senderPool.dictPool[poolKey]
self.dictPool[poolKey][1:2] = [sendQuant]
print("now have",self.dictPool[poolKey][1:2][0])
pass
else:
print("Not a valid targetPool, apparently")

Categories