I am trying to work out how to iterate over a list and print out each item with a print statement describing what element is. my project is to create a user management system and print out something similar to the image I have attached.
The output I am trying to produce
The output I am getting
My code:
records = 0
userFirst = ["John"]
userLast = ["Doe"]
autoUsername = ["Johndoe91"]
autoPassword = ["123456789"]
hiddenPassword = ["*****789"]
userRole = ["User"]
userDept = ["Administration"]
users = []
confidentialUserDetails = []
users.append(userFirst + userLast + userRole + userDept + autoUsername + autoPassword)
confidentialUserDetails.append(users)
for row in range(len(confidentialUserDetails)):
records += 1
print("-" * 25)
print("Record: ", records)
for col in range(len(confidentialUserDetails[row])):
print(confidentialUserDetails[row][col])
Any help would be greatly appreciated. :)
Your data structures are unusual. I'm assuming that those lists are going to be provided to your code somehow and will, in practice, have multiple user details appended to them so that they are all the same length.
Anyhow, you can achieve the output you're looking for with some readable f-strings like this:
from functools import reduce
userFirst = ["John"]
userLast = ["Doe"]
autoUsername = ["Johndoe91"]
autoPassword = ["123456789"]
hiddenPassword = ["*****789"]
userRole = ["User"]
userDept = ["Administration"]
for row in range(len(userFirst)):
s = (f"""\
Name : {userFirst[row]} {userLast[row]}
Role : {userRole[row]}
Department : {userDept[row]}
Username : {autoUsername[row]}
Password : {hiddenPassword[row]}""")
maxlen = reduce(lambda x,y: max(x, len(y)), s.split("\n"), 0)
print(f"{s}\n{'-'*maxlen}\n")
Output:
Name : John Doe
Role : User
Department : Administration
Username : Johndoe91
Password : *****789
------------------------------
I created a dictionary called user instead of your list and after that I appended it to the second list and finally I printed the key and the value of the dictionary.
Also to get the full name I joined userFirst and userLast as string.
Code:
records = 0
userFirst = ["John"]
userLast = ["Doe"]
autoUsername = ["Johndoe91"]
autoPassword = ["123456789"]
hiddenPassword = ["*****789"]
userRole = ["User"]
userDept = ["Administration"]
confidentialUserDetails = [] # 2d list for asterisked passwords
users={'Name' : [' '.join(userFirst + userLast)] ,'Role' : userRole , 'Departement' : userDept ,'Username' : autoUsername ,'Password' : hiddenPassword }
confidentialUserDetails.append(users)
for user in confidentialUserDetails:
records += 1
print("-" * 25)
print("Record: ", records)
for ele,v in user.items():
print(ele,':',v[0])
Output:
-------------------------
Record: 1
Name : John Doe
Role : User
Departement : Administration
Username : Johndoe91
Password : *****789
Using a dictionary or f strings like the two other answers suggested is probably the best. But if you just want to use your current code to print your desired output, you can simply grab each item by its index number in your print statement.
Change the line:
print(confidentialUserDetails[row][col])
To something like this:
print("Name : ", confidentialUserDetails[row][col][0], confidentialUserDetails[row][col][1])
print("Role: : ", confidentialUserDetails[row][col][2])
Output:
-------------------------
Record: 1
Name : John Doe
Role: : User
Query
Balance.objects.filter(~Q(fax_date=F('paused_date')))
returns empty qs even though I do have objects that fit the condition "fax date field not equal to paused date". Is it possible to use ~Q and F together like that?
ran a test like this:
deals = Deal.objects.all()
balance_pre = Balance.objects.filter(~Q(fax_date=F('paused_date')), fax_date__isnull=False, reserved=False)
agr_nums = list(deals.filter(agr_name__isnull=False).values_list('agr_name', flat=True).distinct())
agrs_with_fax = 0
for agr_num in agr_nums:
try:
balance_agr = Balance.objects.get(number__icontains=agr_num)
if balance_agr.fax_date is not None and balance_agr.fax_date != balance_agr.paused_date and not balance_agr.reserved:
agrs_with_fax += 1
except Balance.DoesNotExist:
pass
agrs_with_fax2 = 0
for agr_num in agr_nums:
try:
balance_pre.get(number__icontains=agr_num)
agrs_with_fax2 += 1
except Balance.DoesNotExist:
pass
r = [agrs_with_fax, agrs_with_fax2, balance_agr.fax_date, balance_agr.paused_date, balance_agr.reserved]
r returned is
[55, 0, datetime.date(2018, 7, 11), None, False]
I don't see my error, both cycles should return same result.
I created a Balance model in a fresh project just to test that print(qs.query) will show you the generated query(not in all cases) in this case. I used also exclude as #daniel-roseman suggested to prove that they were equivalent. I hope this help you.
>>> from django.db.models import F, Q
>>> qs = Balance.objects.filter(~Q(fax_date=F('paused_date')))
>>> print(qs.query)
SELECT "so_balance"."id", "so_balance"."fax_date", "so_balance"."paused_date"
FROM "so_balance" WHERE NOT ("so_balance"."fax_date" =
("so_balance"."paused_date"))
>>> qs = Balance.objects.exclude(fax_date=F('paused_date'))
>>> print(qs.query)
SELECT "so_balance"."id", "so_balance"."fax_date", "so_balance"."paused_date"
FROM "so_balance" WHERE NOT ("so_balance"."fax_date" =
("so_balance"."paused_date"))
Suppose I have the following schema in Pony ORM:
from pony.orm import *
db = Database("postgres", database='foo')
class Job(db.Entity):
job_id = PrimaryKey(int, auto=True)
job_name = Required(str)
base_salary = Required(int)
multiplier = Required(int, default=1000)
people = Set(lambda: Person)
class Person(db.Entity):
person_id = PrimaryKey(int, auto=True)
name = Required(str)
job = Required(lambda: Job)
experience = Required(int)
I would like the Person entity to have a salary attribute that's equal to:
Job.base_salary + (Person.experience * Job.multiplier)
My first thought was to add a property to the Person entity like so:
#property
def salary(self):
return self.job.base_salary + (self.experience * self.job.multiplier)
This works for a simple query:
j1 = Job(job_name = "Astronaut", base_salary = 80000, multiplier = 5000)
j2 = Job(job_name = "Butcher", base_salary = 40000, multiplier = 2000)
j3 = Job(job_name = "Chef", base_salary = 30000)
for i, name in enumerate(["Alice", "Bob", "Carol"]):
p = Person(name = name, job=j1, experience = i)
for i, name in enumerate(["Dave", "Erin"]):
p = Person(name = name, job=j2, experience = i)
for i, name in enumerate(["Frank", "Gwen"]):
p = Person(name = name, job=j3, experience = i)
for p in select(p for p in Person):
print p.name, p.experience, p.salary
Prints:
Alice 2 90000
Bob 4 100000
Carol 6 110000
Dave 2 44000
Erin 4 48000
Frank 2 32000
Gwen 4 34000
But if I try something like this:
for j in select((j.job_name, avg(j.people.salary)) for j in Job):
print j
Perhaps unsurprisingly, I get:
AttributeError: j.people.salary
since salary isn't a "real" attribute. Is there a way to do this kind of thing that would allow calculated fields to be treated as first-class entities that can have normal aggregation / calculations done on them?
Thanks for the suggestion!
Currently (Feb 2015) Pony ORM does not support calculated fields, but this feature can be implemented relatively easily, because Pony already have the ability to translate lambdas to SQL. I hope we can add calculated fields soon.
This is a homework question, but as you can see I've written most of the code already. :) What I'm trying to have happen is that the Agent object inherits the methods from the Investor object, as the Agent object's methods are suppose to be basically the same. The only different is the constructors, Investor takes 6 parameters, Agent takes 7. You can see that the parameters are also basically the same.
Investor.load and Investor.report work, for the most part, as expected. The inherited methods in Agent do not. See below.
My main issues:
When I run report(o) on Investor, the output is slightly messed up. It has little paragraph symbols at the end of each line, rather than a carriage return. (I'm developing on linux)
When I run load and report on Agent, it does not populate my arrays (reports and data) as it should. Because of that, report prints nothing. How do I set up my class variables so that they work in the way I want them to?
Thanks!
Will re-add after turnin date.
Here is how the above code SHOULD function.
>>> from sys import stdout as o
>>> import datetime
>>> from hedgefunds import *
>>>
>>> i = Investor('Flintstone','Fred',datetime.date(1965,12,3),'male','Mr.')
>>>
>>> i
Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1)
>>> repr(i)
"Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1)"
>>> i.__repr__() # THIS CONTROLS PREVIOUS TWO LINES
"Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1)"
>>> eval(repr(i)) # OBJECT CAN BE RECREATED FROM ITS REPR STRING
Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1)
>>>
>>> i # NOTICE ONE ADDITIONAL BIT OF DATA WE DIDN'T SPECIFY?
Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1)
>>> # THE '1' AT THE END IS THE RECORD ID rid. THE REPR STRING INCLUDES ALL DATA SO YOU SEE IT.
>>> # THE INVESTOR CLASS SHOULD ASSIGN A rid IF ONE IS NOT PASSED INTO THE CONSTRUTOR.
>>>
>>> print i
1, Mr. Fred Flintstone, 12/03/1965, male
>>> i.__str__() # THIS CONTROLS PREVIOUS LINE
'1, Mr. Fred Flintstone, 12/03/1965, male'
>>>
>>> # NOTE THE NAME IS NICELY PUT TOGETHER AND AND rid IS AT THE START
>>> # NOTE datetime.date(YYYY, MM, DD) BUT WE PRINT IN MM/DD/YYYY FORMAT
>>>
>>> # NOW LET'S LOOK AT OUR INVESTOR OBJECT'S ATTRIBUTES
>>> i.last_name
'Flintstone'
>>> i.first_name
'Fred'
>>> i.dob
datetime.date(1965, 12, 3)
>>> i.date_of_birth
'12/03/1965'
>>> i.gender
'male'
>>> i.title
'Mr.'
>>> i.name
'Mr. Fred Flintstone'
>>> i.rid
1
>>>
>>> # BUT WE'RE GONNA NEED SOMEHWERE TO STORE MULTIPLE INVESTOR OBJECTS
>>> # SO AS WELL AS CREATING INVESTOR OBJECTS, THE INVESTOR CLASS MUST ACT LIKE A RECORDSET
>>>
>>> Investor.report(o) # o WAS SET TO STDOUT AT THE TOP OF THIS TRACE BUT COULD BE ANY FILE
>>> Investor.add(i) # NO RECORDS SO LET'S ADD ONE
>>> Investor.report(o) # NOW WE HAVE SOMETHING TO REPORT
1, Mr. Fred Flintstone, 12/03/1965, male
>>>
>>> Investor.add(Investor('Flintstone','Wilma',datetime.date(1968,1,15),'female','Mrs.'))
>>> Investor.report(o)
1, Mr. Fred Flintstone, 12/03/1965, male
2, Mrs. Wilma Flintstone, 01/15/1968, female
>>>
>>> # WE COULD CONTINUE ADDING INVESTORS MANUALLY BUT SINCE WE'VE GOT A FILE FULL OF THEM....
>>> Investor.load('investors.csv')
>>> Investor.report(o)
1, Mr. Charles Creed, 12/05/1928, male
2, Miss Sheila Geller, 11/12/1962, female
3, Mr. Fred Kenobi, 07/13/1957, male
4, Miss Rachel Geller, 07/11/1968, female
5, Mr. Charles Rubble, 09/23/1940, male
6, Mrs. Leah Skywalker, 07/02/1929, female
7, Mr. Bill Balboa, 03/06/1988, male
8, Dr. Sheila Barkley, 08/26/1950, female
.
.
>>> # YOU SHOULD SEE 120 RECORDS (OUR TWO MANUALLY ADDED RECORDS ARE GONE)
>>>
>>>
>>>
>>> # AGENTS
>>>
>>> a = Agent(2.1,'Rubble','Barney',datetime.date(1966,4,20),'male','Mr.')
>>> a
Agent(2.1000000000000001, 'Rubble', 'Barney', datetime.date(1966, 4, 20), 'male', 'Mr.', 1)
>>> repr(a)
"Agent(2.1000000000000001, 'Rubble', 'Barney', datetime.date(1966, 4, 20), 'male', 'Mr.', 1)"
>>> eval(repr(a))
Agent(2.1000000000000001, 'Rubble', 'Barney', datetime.date(1966, 4, 20), 'male', 'Mr.', 1)
>>> print a
1, Mr. Barney Rubble, 04/20/1966, male, 2.1
>>> a.last_name
'Rubble'
>>> a.first_name
'Barney'
>>> a.dob
datetime.date(1966, 4, 20)
>>> a.date_of_birth
'04/20/1966'
>>> a.gender
'male'
>>> a.title
'Mr.'
>>> a.name
'Mr. Barney Rubble'
>>> a.rid
1
>>> a.commission
2.1000000000000001
>>> Agent.add(a)
>>> Agent.report(o)
1, Mr. Barney Rubble, 04/20/1966, male, 2.1
>>> Agent.load('agents.csv')
>>> Agent.report(o)
1, Mr. Barney Flintstone, 02/13/1933, male, 4.0
2, Miss Rachel Rubble, 11/21/1982, female, 2.5
3, Dr. Ted Geller, 03/14/1963, male, 8.0
4, Miss Phoebe Creed, 11/06/1959, female, 5.5
5, Mr. Luke Kenobi, 08/24/1945, male, 2.5
6, Dr. Megan Creed, 03/26/1957, female, 5.5
7, Mr. Ted Rubble, 09/14/1931, male, 3.5
8, Mrs. Monica Balboa, 05/07/1934, female, 1.5
There is a lot going on here, so I'll try to be brief.
class Investor(object):
reports = []
data = []
def __init__(self, LastName, FirstName, Date, Gender, Title, Rid=1):
# the following two lines define variables which only exist inside
# __init__, so they can basically be gotten rid of.
# reports = []
# data = []
# but they *don't need to be initialized*. Actually creating a new list
# in each constructor is *bad* unless you want one report per instance
# ... later, be sure to add "self" instead of adding to the local vars
self.add(self)
#classmethod
def report(self, o):
result = ""
for x in self.reports:
# Just use join, that's what you mean anyway.
result = ', '.join(x)
# \n should result in \n\n. I think you mean o.write(result)
o.write(result + "\n")
#classmethod
def load(self, f):
self.reports = []
self.data = []
file = open(f)
# why the extra readline?
file.readline()
list = []
while 1:
line = file.readline()
# you need to get rid of the trailing whitespace
items = line[:-1].split(", ")
if not line:
break
else:
# self, here, refers to the class, so you can use it as the
# constructor as well
# use the * to make a list into an argument list.
self(*items)
# No need to add it, the value is added at the end of __init__
# as things stand.
class Agent(Investor):
reports = []
data = []
def __init__(self, Commission, LastName, FirstName, \
Date, Gender, Title, Rid=1):
super(Agent, self).__init__(self, LastName, FirstName, Date, \
Gender, Title, Rid)
self.commission = Commission
def __str__(self):
# Be lazy! Use super!
return super(Agent,self).__str__() + ', ' + self.commission
# this was doing the same thing in the parent class.
# def __repr__(self):
# The classmethod methods are not needed unless you want to redefine
# behavior in a child class.
#classmethod
def add(self, i):
# If you do change something, though, make sure to use super
# here as well...
super(Agent, self).add(i)
I believe that should take care of most of your issues.
If you want to have the format Investor('Flintstone', 'Fred', datetime.date(1965, 12, 3), 'male', 'Mr.', 1), you'll need to include the __name__ and quote the properties:
def __repr__(self):
# notice the " and ' below.
return self.__name__ + "('" + str(self.rid) + "', '" + \
self.name + "', " + self.date_of_birth + ", '" + self.gender + "')"
In Agent you will need to use a sub-string to get what you need:
def __repr__(self):
# remove the Agent( so you can add the commission at the *front*
s = super(Agent,self).__str__()
return self.__name__ + "('" + self.commission + "'," + \
s[len(self.__name__ + 1):]