TL;DR
Change:
usuarios = list({'nome': 'marcelo', 'senha': 'marcelo123'})
# por:
usuarios = [{'nome': 'marcelo', 'senha': 'marcelo123'}]
And:
if usuario['nome'] not in usuarios['nome']:
# por:
if usuario['nome'] not in {u['nome'] for u in usuarios}:
It seems you still don’t quite understand how to use python’s data structures. I’ll try to explain what I think you still don’t understand.
Creation of list of dictionaries
Your code:
usuarios = list({'nome': 'marcelo', 'senha': 'marcelo123'})
The content of usuarios
now is ['nome', 'senha']
, and it’s not what you expected. To understand the reason we need to understand what list()
ago.
To documentation of list()
shows that list
receives an iterable as parameter, so you could pass any iterable that list()
will iterate over the received argument and add each item of that iteration to the new created list.
For teaching purposes, it would be like:
def list(iteravel):
nova_lista = [] # cria a nova lista
for item in iteravel:
nova_lista.append(item) # adiciona o item à nova lista
return nova_lista # retorna a nova lista criada
Knowing this, we went back to your code. You’re passed a dictionary to list()
, how dictionaries are iterable is okay, but when you iterate over a dictionary, you iterate over your keys. In documentation of dict
you will see that call iter(d)
is just a shortcut to iter(d.keys)
. Example:
dicionario = {
'chave_1': 'Valor 1',
'chave_2': 'Valor 2',
'chave_3': 'Valor 3',
}
for item in dicionario:
print(item)
# chave_1
# chave_2
# chave_3
So your code:
usuarios = list({'nome': 'marcelo', 'senha': 'marcelo123'})
It would be like you were doing:
usuario = []
for chave in {'nome': 'marcelo', 'senha': 'marcelo123'}:
usuario.append(chave)
# usuario = ['nome', 'senha']
What you really want is a list of dictionaries, where each dictionary corresponds to a user of your system. To do this:
usuarios = [{'nome': 'marcelo', 'senha': 'marcelo123'}]
Checking of user existence
Checking a user’s existence on your system will depend on the structure used to store your users.
I will take it as true that you have corrected your code and are using a list of dictionaries, as the previous response section explained.
The operator in
, when used in sequences test if an item in the list has value equal to the searched item. That is, 1 in [0, 1, 2]
would be like testing:
def contem(valor, sequencia):
for item in sequencia:
if item == valor
return True
return False
contem(1, [0, 1, 2]) # True
contem(5, [0, 1, 2]) # False
I explain this because if you look at Dict documentation you’ll see that it says:
Dictionaries compare Equal if and only if they have the same (key, value) pairs (regardless of Ordering).
Free translation:
Dictionaries are treated as equals in a comparison if, and only if, they have the same key and value pairs (regardless of their order).
That is, if you test yourself dict_a == dict_b
the result will be based on your keys and values, even if they refer to different objects in memory (my answer and the answer accepts of this question explain a little more about this). So:
dict_1 = {'chave_1': 1, 'chave_2': 2}
dict_2 = {'chave_2': 2, 'chave_1': 1}
dict_1 == dict_2
# True
dict_1 is dict_2
id(dict_1) == id(dict_2)
# False para ambos (mesmo valor, mas objetos diferentes)
Moral of the story, if you test your object directly in the user list will only work if your object also has the key senha
as the correct value in the listing.
usuarios = list({'nome': 'marcelo', 'senha': 'marcelo123'})
'marcelo' in usuarios
# False
{'nome': 'marcelo'} in usuarios
# False
{'nome': 'marcelo', 'senha': 'marcelo123'} in usuarios
# True
A good way out is to create a set()
with the names already registered and test the existence in this set()
. Your code would look like this:
cadastros = {u['nome'] for u in usuarios}
if usuario['nome'] not in cadastros:
break
You can see more about set()
and comprehensiset on in the documentation.
Just to remind you that the operation
in
is more performative when applying the sets (O(1)) than in lists (O(n)). So you could just exchange forusuarios_existentes = {user['nome'] for user in usuarios}
if your user list is too large. ;)– fernandosavio
PS: I don’t think I should add that to the answer, it’s just to leave an observation for future visitors.
– fernandosavio