Python dict inside list doesn't append - python

this is my code.
# Lista de usuarios
UserList = []
UserDic = {}
UserListQuery = UserProfile.objects.all()
print "PRINTING QUERY " + UserListQuery
for User in range(0,len(UserListQuery)):
UserDic['username'] = UserListQuery[User].user.get_username()
UserDic['titulo'] = UserListQuery[User].titulo
UserDic['descripcion'] = UserListQuery[User].descripcion[:60]
UserList.append(UserDic)
print "PRINTING LIST " + UserList
print "PRINTING LIST 0 " + UserList[0]
I want UserList to be a dict list. I mean, if I print UserList[0]['username'], it has to return me the username in the position 0. Well, I've many users. I use append and I'm adding the user to the list. It's not working well, it overwrites the user resulting in a one position list, the last user from UserListQuery.
help?

The issue here is, that the same UserDic object gets used in each loop, so each time UserDic['username'] gets overwritten with the new value. To prevent this you must create a new UserDic every time. The following should work:
# Lista de usuarios
UserList = []
UserListQuery = UserProfile.objects.all()
for User in range(0,len(UserListQuery)):
UserDic = {}
UserDic['username'] = UserListQuery[User].user.get_username()
UserDic['titulo'] = UserListQuery[User].titulo
UserDic['descripcion'] = UserListQuery[User].descripcion[:60]
UserList.append(UserDic)
print UserList
(Untested code)

per my comment you should try this
user_list = []
user_list_query = user_profile.objects.all()
for user in range(0,len(user_list_query)):
user_list.append({
'username': user_list_query[user].user.get_username(),
'titulo' : user_list_query[user].titulo,
'descripcion': user_list_query[user].descripcion[:60]
})
print user_list
note i also changed the naming convention of your objects since python is preferred to use underscores between the names instead of capital letters
an even better way (more pythonic) to do it would be to remove all the excess stuff and just go with a single line loop
user_list_query = user_profile.objects.all()
print [{'username': user_list_query[user].user.get_username(), 'titulo' : user_list_query[user].titulo,'descripcion': user_list_query[user].descripcion[:60]} for user in range(0,len(user_list_query))]

Related

Changing string to avoid duplication in a systematic manner?

Take the list Usernames as shown below.
Usernames = ["johnsmith"]
I have the variable NewUsername and I need to check if its value is already contained in the list. If not, an integer will be concatenated to the end of it.
Examples:
NewUsername = "alexsmith"
Usernames = ["johnsmith", "alexsmith"]
NewUsername = "johnsmith"
Usernames = ["johnsmith", "alexsmith", "johnsmith1"]
NewUsername = "johnsmith"
Usernames = ["johnsmith", "alexsmith", "johnsmith1", "johnsmith2"]
Now, I know I can do this with something like this, but it would only check for the first 'level' of duplicate names.
if NewUsername in Usernames:
NewUsername = NewUsername + "1"
Usernames.append(NewUsername)
Question: How can I handle all duplications in a similar manner?
Maybe is a bit elaborate, but you could use a custom child class of a list. To give you an idea:
from collections import Counter
class UsernameList(list):
def __init__(self, *args):
super(UsernameList, self).__init__()
self._ucount = Counter()
for e in args[0]:
self.append(e)
def append(self, el):
if isinstance(el, str):
if self._ucount[el] == 0:
super(UsernameList, self).append(el)
else:
fixel = el + str(self._ucount[el])
super(UsernameList, self).append(fixel)
self._ucount.update([fixel])
self._ucount.update([el])
else:
raise TypeError("Only string can be appended")
Now you could do:
Usernames = UsernameList(["johnsmith"]) #Username is ["johnsmith"]
Usernames.append("johnsmith") #Username becomes ["johnsmith", "johnsmith1"]
Usernames.append("johnsmith") #Username becomes ["johnsmith", "johnsmith1", "johnsmith2"]
Apart the new __init__ and append methods, UsernameList has all the methods of a list, and works exactly as a list. Don't bother about the counter attribute, it's there to keep track of the usernames inputed and add the correct number in case of repetitions.
To have something more consistent you may need to override other methods: i'm just giving you an idea, far from writing a full working code here.
You may have a look at the docs for more details on which methods you may need to override.

Setting a dictionarys items to a variable

I was wondering if this would be possible, to save a dictionary item to a variable. So simply this is what I am doing. I am saving this item to a dictionary:
accounts{}
def accountcreator():
newusername = raw_input()
newpassword = raw_input()
UUID = 0
UUID += 1
accounts[newusername] = {newpassword:UUID}
Now basically I will be looping through the newusernames in a separate function:
def accounts():
username = raw_input()
for usernames in accounts:
if usernames == username:
#Not sure what to do from here on out
else:
accounts()
This is where I get confused. So if the username input equals a newusername in the accounts dictionary it will contiune on. I want it to save that newusernames password and UUID (the {newpassword:UUID} part) to a variable. So basically if the newusername equals the username input it will save the rest of thats informations (the {newpassword:UUID}) to a variable. So in the end the variable lets say accountinfo = {newpassword:UUID}. Thank you, I hope that makes sense.
There are a couple of errors in your code. First, probably a typo:
accounts = {}
Next, when you create the code, you are always resetting UUID to 0, making the increment a little pointless. Initialize UUID outside the function, like you do with accounts:
UUID = 0
def accountcreator():
newusername = raw_input()
newpassword = raw_input()
UUID += 1
accounts[newusername] = {newpassword:UUID}
Third, I'm not sure why you are mapping the password to the UUID. Likely, you want two separate fields in the user dictionary to store both:
accounts[newusername] = { 'password': newpassword, 'UUID': UUID }
Finally, the whole point of using a dictionary to map user names to information is that you don't need to iterate over the entire dictionary; you just index the dictionary with the user name. You do have to take care that you don't try to access a nonexistent key, though.
# Use a different name; accounts is already a dictionary
def get_account():
username = raw_input()
if username in accounts:
return accounts[username]
else:
print("No account for {0}".format(username))

python: changing from print to return does not process items right

I created a program that reads a couchDB to list followers and friends ids of a single twitter user. Friends are identified under the group “friend_edges” and followers under “follower_edges”.
I use the intersection operation between sets -set1.intersection(set.2)- in order to obtain the list of those who are both friends and followers.
When I use print to see the outputs, the results are correct. But when I change to return to process the results, it only processes friends, not followers.
Can somebody give me a clue of what I'm doing wrong and how to improve the code?.... thanks in advance.
from twitter_login import oauth_login
from twitter_DB import load_from_DB
from sets import Set
def friends_and_followers(doc):
if 'friend_edges' in doc.keys():
flist = []
for x in doc['friend_edges']:
flist.append(x)
#print "Number of friends: ", len(flist) <-- shows the right number of items
return flist
else:
return []
if 'follower_edges' in doc.keys():
followlist = []
for x in doc['follower_edges']:
followlist.append(x)
#print "Number of followers: ", len(followlist) <-- shows the right number of items
return followlist
else:
return []
flist = Set(flist)
followlist = Set(followlist)
return flist.intersection(followlist)
if __name__ == '__main__':
twitter_api = oauth_login()
DBname = 'users-aguy-+-only'
ff_results = load_from_DB(DBname)
print 'number loaded', len(ff_results)
for doc in ff_results:
together = friends_and_followers(doc)
print "Friends and followers of a guy: ", together
A return statement stops execution of that method and returns to the calling method, so by adding a return statement you are saying, "Stop here and go back to where you came from"
You need to store both the values you want returned in variables and return them at the same time at the end of your method:
return value1, value2
You will call this with something like this:
val1, val2 = get_value1_and_value2(input)
It might make more sense to just break that up into two separate methods that each return the correct value though.

Remove element in a list with condition

I have a class named Info where Info has a string type instance variable which can be accessed by Info.getName()
Also I have a list of instance Info such as class_list = [Info('Aleck'), Info('John')].
Given a name_list = ['Aleck', 'Bob'], I would like to remove the element in class_list with the same name in name_list, while i also need to know if a name (such as Bob) is not in class_list (for example print out that bob is not in list)
for above example the result should be class_list = [Info('John')] and print out that bob is not on the list.
I know ugly way of doing so such as the following codes (i am not actually running it, just an example), is there elegant or Pythonic way to do this?
def removeElement(name_list, class_list):
list_to_be_removed = []
for name in name_list:
is_name_in_list = false
for obj in class_list
if name == obj.getName():
list_to_be_removed.add(obj)
is_name_in_list = true
break
if is_name_in_list == false:
print name + ' is not in the list'
is_name_in_list = false
for obj in list_to_be_removed:
class_list.remove(obj)
You don't have classes, you have class instances. Info('Alice') is a constructor call, that creates an instance of your Info class.
How about this:
filtered = [info for info in info_list if info.get_name() not in name_list]
Alternatively:
filtered = filter(lambda o: o not in name_list, info_list)
If you have a lot of names convert your name_list into a set and use that.
name_set = set(name_list)
List comprehensions are your friend.
def remove_names(names_to_remove, info_list):
return [info
for info in info_list
if info.getName() not in names_to_remove]
I changed the names of most variables to be closer to what I think you mean.

Printing object attributes based on user input in Python 3x

First of all I'd like to say im a Python beginner (or programming beginner for that matter) and I'm trying to figure out how to print attributes from a object based on user input.
This is the code I have so far:
class Customer:
"De klasse customer"
def __init__(self, naam, adres, woonplaats, email):
self.naam = naam
self.adres = adres
self.woonplaats = woonplaats
self.email = email
input1 = input ("Enter the object name")
print(input1.naam) ## ** << This is what i like to know**
a = Customer('Name1', 'address', 'Utrecht', 'Email1#hotmail.com')
b = Customer('Name2', 'Bonestaak', 'Maarssen', 'Bijjaapishetaltijdraakhotmail.com')
So I basically want this: print(a.naam) to work, but the 'a' must be entered by a user.
Did some searching but no success so far.
You can use the locals function:
>>> a = {1:'abc'}
>>> obj = raw_input('Obj?> ')
Obj?> a
>>> print locals()[obj][1]
abc
>>>
This is however an highly insecure construct (there are other things in locals!)
A cleaner way would be to:
customers = {
'a' : Customer('Name1', 'address', 'Utrecht', 'Email1#hotmail.com')
'b' : Customer('Name2', 'Bonestaak', 'Maarssen', 'Bijjaapishetaltijdraakhotmail.com')
}
customer = raw_input('Customer? > ')
print customers[customer].naam
You'll need to handle KeyError properly though!

Categories