Reading from subdict in python3 - python-3.x

I have 2 dict. One with local player data and one listing the players with subdictionaries:
class GameData:
def __init__(self):
self.player = {'id' : 1453339642,
'positionX' : 123,
'positionY' : 0
}
self.players = {1453339642:
{'name' : "Admin"}
}
gameData = GameData()
Then I print out just to check if everything works:
for x in gameData.player:
print (str(x),':',gameData.player[x])
print("\n\n")
for x in gameData.players:
print (str(x))
for y in gameData.players[x]:
print (' ',y,':',gameData.players[x][y])
print("\n\n")
This results in:
id : 1453339642
positionY : 0
positionX : 123
1453339642
name : Admin
When I now want to access the player's id in players for instance with
#print(str(type(gameData.player)))
#print(str(type(gameData.players)))
print(str(type(gameData.players[1453339642])))
I get KEYERROR as a result. Why?

If I put this in a file, it works:
class GameData:
def __init__(self):
self.player = {'id' : 1453339642,
'positionX' : 123,
'positionY' : 0
}
self.players = {1453339642:
{'name' : "Admin"}
}
gameData = GameData()
print(str(type(gameData.players[1453339642])))
Only indentation differs from your code. There must be something happening to gameData between instantiation and the final print.

Related

Filter and group the values in python

I have a file with below content:
a.ganesh : sp-tns-ops-dashboard
a.ganesh : tns-extern
a.shahnawaz : pricing-dm-rest
a.shubhamkumar : apl
aadhar.sachdeva : athena
aakash.j : cms-cs-gateway
aakash.j : cms-enrichment-console
aakash.j : sp-slm-sps-external
aakash.j : preprod-cms-localisation-gateway
I am trying to filter and get the output in below format:
[[a.ganesh: ["sp-tns-ops-dashboard", "tns-extern"]], [a.shahnawaz: ["pricing-dm-rest"]], [aakash.j: ["cms-cs-gateway", "cms-enrichment-console", "sp-slm-sps-external", "preprod-cms-localisation-gateway"]]]
Tried something like:
def test():
lst1 = []
for i in open("sorted_list.txt").readlines():
strip = i.strip()
parts = lst1.append(strip.split(":"))
lst2 = []
for j in lst1:
if j[0] not in lst2:
lst2.append(f"{j[0]} : {j[1]}")
print(lst2)
I understand there's a logic mistake, but can I get a help here
Try to play with this:
keys = set()
dictList = dict()
for l in lst1:
keys.add(l[0])
dictList.setdefault(l[0],[]).append(l[1])
lst2 = dictList.items()

Create a python Class inheriting from a Class created by a function

What works :
I am using the module recordtype to store global parameters for the different functions of my program.
Each parameter is a class instance of :
class Parameter(object):
def __init__(self, name, value, info):
self.name = name
self.value = value
self.info = info
Then the global structure is defined like this :
The individual parameters :
parameter_1 = Parameter('param_1', 10, 'Value for the parameter 1, usage...')
parameter_2 = Parameter('param_2', 20, 'Value for the parameter 2, usage...')
...
parameter_m = Parameter('param_n', 50, 'Value for the parameter m, usage...')
parameter_n = Parameter('param_n', 100, 'Value for the parameter n, usage...')
Parameter sub sets :
parameter_set_1 = recordtype('parameter_set_1', [(parameter_1.name, parameter_1),
(parameter_2.name, parameter_2), ...])
...
parameter_set_n = recordtype('parameter_set_n', [(parameter_m.name, parameter_m),
(parameter_n.name, parameter_n)]
The global parameter structure is then :
GlobalParametersFunction = recordtype('GlobalParameters', [('parameter_set_1', parameter_set_1()),
('parameter_set_2', parameter_set_2()), ('parameter_set_n', parameter_set_n())])
Which needs to be instantiated :
GlobalParameters = GlobalParameterFunction()
This all works well, the GlobalParameterFunction creates a class where I can access individual parameters and change their values, Ex:
GlobalParameters.parameter_set_1.parameter_1.value = 20
From the GlobalParameters class instance I can then make a function that prints the values and their names :
def print_parameter_info(GP):
for field, val in zip(GP._asdict(), GP._asdict().values()):
print(field, ':')
for key, entry in zip(val._asdict(), val._asdict().values()):
print('\t', entry.name, ':', entry.value)
Which does a nice print for the user :
>>> print_parameter_info(GlobalParameters)
parameter_set_1 :
parameter_1 : 10
parameter_2 : 20
parameter_set_n :
parameter_m : 50
parameter_n : 100
I would also like to create a function such that :
change(GlobalParameters, 'name', new_value)
does :
GlobalParameters.parameter_set_1.name.value = new_value
Which seems easily doable with the class created by recordtype
The problem :
I would like to create a class methods for the GlobalParameters class instance, from the print_parameter_info() function such that :
GlobalParameters.print_parameter_info()
and
GlobalParameters.change(name, new_value)
works
because GlobalParameters is a class instance of recordtype, I tried :
class GlobalParameterClass(recordtype):
def __init__(self):
self = GlobalParameterFunction()
But because recordtype is a function creating a class ?
I get the following error :
TypeError: function() argument 'code' must be code, not str
I found this question (2231427)
But after trying to import the right thing and looking at the source code of recordtype I think I understood that recordtype does not define a class clearly and creates it by parsing a string of code ?
Thus I do not understand how to create a class inheriting from the class created by recordtype
I also tried
class GlobalParameterClass(object):
def __init__(self, *args):
self = GlobalParameterFunction(*args)
This does not raise any errors but the class instance created is empty.
TLDR/Conclusion
How can I add custom methods to the class created by the recordtype function from the recordtype module ?
Or
Perhaps, there is there a better way to manage the GlobalParameters object ?
Thank you !
I found a solution without using the recordtype object, by creating a custom classes with the desired behavior :
class Parameter(object):
"""
A class to store the individual sound parameters
"""
def __init__(self, name, value, info):
self.name = name
self.value = value
self.info = info
class ParameterSet(object):
"""
A class to store multiple parameters as a set
"""
def __init__(self, name, *parameters):
self.name = name
for parameter in parameters:
setattr(self, parameter.name, parameter)
class GlobalParameters(object):
"""
A class to store the parameter sets and to be used to assign parameter values to the different functions
"""
def __init__(self, *parameter_sets):
for parameter_set in parameter_sets:
setattr(self, parameter_set.name, parameter_set)
The methods of the GlobalParameters classes go as follow :
def info(self):
for parameter_set in self.__dict__.values():
print(parameter_set.name)
parameters = [parameter for parameter in parameter_set_1.__dict__.values() if type(parameter) != str]
for parameter in parameters:
print('\t', parameter.name, ':', parameter.value)
def change(self, name, value):
for parameter_set in self.__dict__.values():
parameters = [parameter for parameter in parameter_set_1.__dict__.values() if type(parameter) != str]
for parameter in parameters:
if parameter.name == name:
parameter.value = value
With this example code :
# Individual parameters
parameter_1 = Parameter('parameter_1', 10, 'Value for the parameter 1, usage...')
parameter_2 = Parameter('parameter_2', 20, 'Value for the parameter 2, usage...')
parameter_n = Parameter('parameter_n', 50, 'Value for the parameter n, usage...')
parameter_m = Parameter('parameter_m', 100, 'Value for the parameter m, usage...')
# Parameter sets
parameter_set_1 = ParameterSet('parameter_set_1', parameter_1, parameter_2)
parameter_set_2 = ParameterSet('parameter_set_n', parameter_n, parameter_m)
# Global parameter set
GP = GlobalParameters(parameter_set_1, parameter_set_2)
I get the desired behavior :
>>> GP.info()
parameter_set_1
parameter_1 : 10
parameter_2 : 20
parameter_set_n
parameter_1 : 10
parameter_2 : 20
As well as with the .change method :
>>> GP.parameter_set_1.parameter_1.value
10
GP.change('parameter_1', 15)
>>> GP.parameter_set_1.parameter_1.value
15

How to delete an item in EmbeddedDocumentListField in mongoengine?

Here is my data structure:
{
house_id : 1,
houseType : "condo" ,
family: [
{'name': "pete", "gender": "male", etc},
{'name': "jon", "gender": "male", etc}
]
}
How do i delete 'pete' from the EmbeddedDocumentListField?
db = MongoEngine()
db.init_app(app)
class Family(db.EmbeddedDocument):
name = db.StringField()
gender = db.StringField()
class House(db.Document):
house_id = db.IntField(required=True, unique=True)
housingType = db.StringField(required=True)
family = db.EmbeddedDocumentListField(Family)
#app.route('/api/del_member/<h_id>/<fam_name>', methods=['DELETE'])
def del_member(h_id, fam_name):
try:
h = House.objects.get(house_id=h_id)
t = h.family.get(name=fam_name)
return make_response(jsonify(t), 200)
except Exception:
return make_response(f'Something went wrong trying to delete '
f'Member: {fam_name} in House ID: {h_id}', 500)
im able to select the item im interested in but i cant delete it. I have tried .delete() but an error saying
t = h.family.get(name=fam_name).delete()
AttributeError: 'Family' object has no attribute 'delete'
pops up.
I found a solution. Might not be the best but it works. Hopefully someone can improve on it.
#app.route('/api/del_member/<h_id>/<fam_name>', methods=['DELETE'])
def del_member(h_id, fam_name):
h = House.objects.get(house_id=h_id).to_json()
h = json.loads(h)
family = h['family']
new_family = family.copy()
for i in range(len(family)):
name = family[i].get('name')
if name == fam_name:
del new_family[i]
break
House.objects.get(house_id=h_id).update(family=new_family)
return make_response('', 200)

Accessing Class attribute from a called function?

Let say I have something like this :
--module1
def called():
if caller.class.attrX == 1 : ...
--module2
class ABC:
attrX = 1
def method():
called()
I want to access caller Class-attribute ?
I know I have to use inspect somehow but can figure how exactly.
python3
Passing a variable to the function is the best (and only?) option.
--module1
def called(attrX):
if attrX == 1 : ...
--module2
class ABC:
self.attrX = 1
def method():
called(self.attrX)
This seems to work for object variable :
/if I can make it work for class-var it will be better/
import inspect
def say(*args, **kwargs) :
obj = inspect.currentframe().f_back.f_locals['self']
if hasattr(obj,'aaa') : print('hasit')
else : print("no")
class ABC:
aaa = 2
def test(self):
say(123)
i.e. if I dont have 'aaa' set in advance :
In [8]: a.test()
no
In [9]: ABC.aaa = 2
In [10]: a.test()
no
In [12]: a.aaa = 3
In [13]: a.test()
hasit

Read records from CSV file and print report

I have been working on a program for a week now, but have been unable to get it to work according to the guidelines.
In this program (payroll.py), I have to open the CSV data file (employees.csv), read the records in the file, and produce a payroll report using the functions in payroll.py. The output should be printed, not written to a separate output file, and should end up looking like this:
LastName FirstName Hours RegHours OTHours RegPay OTPay GrossPay Deductions NetPay
Hightower Michael 42.0 40.0 2.0 400.00 30.00 430.00 107.07 322.93
Jackson Samuel 53.0 40.0 13.0 506.00 246.68 752.67 187.42 565.25
Jones Catherine 35.0 35.0 0.00 680.05 0.00 680.05 169.33 510.72
The payroll program works just fine on its own (without calling the CSV file), but when I try to call the file (using "from csv import reader"), one of two things happens:
1) I can call the first three columns (last name, first name, and hours), but I am unable to "insert" the additional columns (I get an index error because, of course, those columns don't exist in the original CSV file), or
2) The program only pulls up one entire record, which happens to be the last record in the CSV file.
Any guidance on how to accomplish this would be greatly appreciated. Thank you.
Here is the code for payroll.py:
def main() :
employeeFirstName, employeeLastName = employeeFullName()
employeePayRate, employeeHoursWorked = employeePay()
employeeRegularHours, employeeOvertimeHours = calculateRegularHours(employeeHoursWorked)
employeeOvertimeHours = calculateOvertimeHours(employeeHoursWorked)
employeeTotalHours = calculateTotalHours(employeeRegularHours, employeeOvertimeHours)
regularPayAmount = calculateRegularPay(employeePayRate, employeeRegularHours)
overtimePayAmount = calculateOvertimePay(employeePayRate, employeeOvertimeHours)
grossPayAmount = calculateGrossPay(regularPayAmount, overtimePayAmount)
federalTaxWithheld = calculateFederalTax(grossPayAmount)
stateTaxWithheld = calculateStateTax(grossPayAmount)
medicareTaxWithheld = calculateMedicareTax(grossPayAmount)
socSecTaxWithheld = calculateSocSecTax(grossPayAmount)
totalTaxesWithheld = calculateTotalTaxes(federalTaxWithheld, stateTaxWithheld, medicareTaxWithheld, socSecTaxWithheld)
netPayAmount = calculateNetPay(grossPayAmount, totalTaxesWithheld)
payrollSummaryReport(employeeFirstName, employeeLastName, employeePayRate, employeeRegularHours, employeeOvertimeHours, employeeTotalHours, regularPayAmount, overtimePayAmount, grossPayAmount, federalTaxWithheld, stateTaxWithheld, medicareTaxWithheld, socSecTaxWithheld, totalTaxesWithheld, netPayAmount)
def employeeFullName() :
employeeFirstName = str(input("Enter the employee's first name: "))
employeeLastName = str(input("Enter the employee's last name: "))
return employeeFirstName, employeeLastName
def employeePay() :
employeePayRate = float(input("Enter the employee's hourly pay rate: "))
employeeHoursWorked = float(input("Enter the employee's hours worked: "))
return employeePayRate, employeeHoursWorked
def calculateRegularHours(employeeHoursWorked) :
if employeeHoursWorked < 40 :
employeeRegularHours = employeeHoursWorked
employeeOvertimeHours = 0
else:
employeeRegularHours = 40
employeeOvertimeHours = employeeHoursWorked - 40
return employeeRegularHours, employeeOvertimeHours
def calculateOvertimeHours(employeeHoursWorked) :
if employeeHoursWorked > 40 :
employeeOvertimeHours = employeeHoursWorked - 40
else :
employeeOvertimeHours = 0
return employeeOvertimeHours
def calculateTotalHours(employeeRegularHours, employeeOvertimeHours) :
employeeTotalHours = employeeRegularHours + employeeOvertimeHours
return employeeTotalHours
def calculateRegularPay(employeePayRate, employeeHoursWorked) :
regularPayAmount = employeePayRate * employeeHoursWorked
return regularPayAmount
def calculateOvertimePay(employeePayRate, employeeOvertimeHours) :
overtimePayRate = 1.5
overtimePayAmount = (employeePayRate * employeeOvertimeHours) * overtimePayRate
return overtimePayAmount
def calculateGrossPay(regularPayAmount, overtimePayAmount) :
grossPayAmount = regularPayAmount + overtimePayAmount
return grossPayAmount
def calculateFederalTax(grossPayAmount) :
federalTaxRate = 0.124
federalTaxWithheld = grossPayAmount * federalTaxRate
return federalTaxWithheld
def calculateStateTax(grossPayAmount) :
stateTaxRate = 0.049
stateTaxWithheld = grossPayAmount * stateTaxRate
return stateTaxWithheld
def calculateMedicareTax(grossPayAmount) :
medicareTaxRate = 0.014
medicareTaxWithheld = grossPayAmount * medicareTaxRate
return medicareTaxWithheld
def calculateSocSecTax(grossPayAmount) :
socSecTaxRate = 0.062
socSecTaxWithheld = grossPayAmount * socSecTaxRate
return socSecTaxWithheld
def calculateTotalTaxes(federalTaxWithheld, stateTaxWithheld, medicareTaxWithheld, socSecTaxWithheld) :
totalTaxesWithheld = federalTaxWithheld + stateTaxWithheld + medicareTaxWithheld + socSecTaxWithheld
return totalTaxesWithheld
def calculateNetPay(grossPayAmount, totalTaxesWithheld) :
netPayAmount = grossPayAmount - totalTaxesWithheld
return netPayAmount
def payrollSummaryReport(employeeFirstName, employeeLastName, employeePayRate, employeeRegularHours, employeeOvertimeHours, employeeTotalHours, regularPayAmount, overtimePayAmount, grossPayAmount, federalTaxWithheld, stateTaxWithheld, medicareTaxWithheld, socSecTaxWithheld, totalTaxesWithheld, netPayAmount) :
print()
print("\t\t\t\t\t\tPayroll Summary Report")
print()
print("%-12s%-12s%-8s%-10s%-10s%-12s%-10s%-11s%-13s%-10s" % ("LastName", "FirstName", "Hours", "RegHours", "OTHours", "RegPay", "OTPay", "GrossPay", "Deductions", "NetPay"))
print("%-12s%-12s%-8.2f%-10.2f%-10.2f$%-11.2f$%-9.2f$%-10.2f$%-12.2f$%-10.2f" % (employeeLastName, employeeFirstName, employeeTotalHours, employeeRegularHours, employeeOvertimeHours, regularPayAmount, overtimePayAmount, grossPayAmount, totalTaxesWithheld, netPayAmount))
main ()
The CSV file (employees.csv) I need to use looks like this:
First,Last,Hours,Pay
Matthew,Hightower,42,10
Samuel,Jackson,53,12.65
Catherine,Jones,35,19.43
Charlton,Heston,52,10
Karen,Black,40,12
Sid,Caesar,38,15
George,Kennedy,25,35
Linda,Blair,42,18.6
Beverly,Garland,63,10
Jerry,Stiller,52,15
Efrem,Zimbalist,34,16
Linda,Harrison,24,14
Erik,Estrada,41,15.5
Myrna,Loy,40,14.23
You can treat your .csv file as a regular one. No need for reader. Here is a function that might deal with your file:
def get_data(fname):
'''
Function returns the dictionary with following
format:
{ 0 : {
"fname": "...",
"lname": "...",
"gross": "...",
},
1 : {
....,
,,,,
},
}
'''
result = {} # return value
i = 0 # you can zip range() if you want to
with open(fname, 'r') as f:
for line in f.readlines()[1:]:
result[i] = {}
tmp = line.split(",") # list of values from file
# access file values by their index, e.g.
# tmp[0] -> first name
# tmp[1] -> last name
# tmp[2] -> hours
# tmp[3] -> pay rate
# do calculations using your functions (calculateOvertimePay,
# calculateTotalHours, etc.) and store the results in dictionary
# e.g:
result[i]["fname"] = tmp[0]
result[i]["lname"] = tmp[1]
# ...
# do calculations for report
# ...
# result[i]["regular"] = calc...(....)
# result[i]["overtime"] = calc...(....)
result[i]["gross"] = calculateGrossPay(result[i]["regular"], result[i]["overtime"])
i += 1
return result
There are several thing your might want to do with your payrollSummaryReport(...) function to improve it:
replace your huge argument list with dict, or list
tinker it a bit to fit your requirements
Your might do your improvements in this way:
def payrollSummaryReport(vals) :
print()
print("\t\t\t\t\t\tPayroll Summary Report")
print()
print("%-12s%-12s%-8s%-10s%-10s%-12s%-10s%-11s%-13s%-10s" %\
("LastName", "FirstName", "Hours", "RegHours", "OTHours", "RegPay", "OTPay", "GrossPay", "Deductions", "NetPay"))
for i in vals:
print("%-12s%-12s%-8.2f%-10.2f%-10.2f$%-11.2f$%-9.2f$%-10.2f$%-12.2f$%-10.2f" %\
(vals[i]["fname"], vals[i]["lname"], vals[i]["gross"], ''' repeat for all fields '''))

Resources