Issue
I have a simple class defined like this:
class User(object):
def __init__(self, id=None, name=None):
self.id = id
self.name = name
def __contains__(self, item):
return item == self.id
Using this class, I can do simple checks of single instances of the class like so:
>>> user1 = User(1, 'name_1')
>>> 1 in user1
True
>>> 2 in user1
False
This is working as expected.
How can I check if a value is in a list of User
objects though? It always seems to return False.
Example:
from random import randint
from pprint import pprint
users = [User(x, 'name_{}'.format(x)) for x in xrange(5)]
pprint(users, indent=4)
for x in xrange(5):
i = randint(2,6)
if i in users:
print("User already exists: {}".format(i))
else:
print("{} is not in users list. Creating new user with id: {}".format(i, i))
users.append(User(i, 'new_user{}'.format(i)))
pprint(users, indent=4)
This creates output similar to this:
[ 0 => name_0,
1 => name_1,
2 => name_2,
3 => name_3,
4 => name_4]
6 is not in users list. Creating new user with id: 6
6 is not in users list. Creating new user with id: 6
6 is not in users list. Creating new user with id: 6
3 is not in users list. Creating new user with id: 3
3 is not in users list. Creating new user with id: 3
[ 0 => name_0,
1 => name_1,
2 => name_2,
3 => name_3,
4 => name_4,
6 => new_user6,
6 => new_user6,
6 => new_user6,
3 => new_user3,
3 => new_user3]
The issue is that the user with id 6
should have only been created 1 time, because it wasn't created already. The second and third time that 6
was attempted, it should have failed. The user would id 3
shouldn't have been recreated at all because it was part of the initialization of the users
variable.
How do I modify by __contains__
method to be able to properly utilize in
when comparing against multiple instances of my class?
Solution
This is a misuse of __contains__
. You would expect to implement __contains__
on a class like UserList
.
A better way to do this is to just access the id
attribute directly in generator expression or list comprehension (rather than using the in operator). eg.
class User(object):
def __init__(self, id=None, name=None):
self.id = id
self.name = name
user = User(1, 'name_1')
assert 1 == user.id
user_list = [user, User(2, 'name_2')]
assert any(2 == u.id for u in user_list)
Then for your random example, you'd use a set or dictionary to store the ids of the users that already exist.
users = [User(x, 'name_{}'.format(x)) for x in xrange(5)]
ids = set(u.id for u in users)
for x in xrange(5):
i = randint(2,6)
if i in ids:
print("User id already exists: {}".format(i))
else:
print("{} is not in users list. Creating new user with id: {}".format(i, i))
ids.add(i)
users.append(User(i, 'new_user{}'.format(i)))
Answered By - Dunes
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.