开发者

Python While Loop Issue

开发者 https://www.devze.com 2023-03-20 02:50 出处:网络
I\'m blanking here. I want to grab all the users from the userbase, but then only loop through 10 of them (I\'m leaving out code that would explain why I wouldn\'t just grab 10 users from the db in th

I'm blanking here. I want to grab all the users from the userbase, but then only loop through 10 of them (I'm leaving out code that would explain why I wouldn't just grab 10 users from the db in the first place).

users = User.objects.all()
i = 0
while i < 10:
    for user in users:
        if user.is_active:
            # do something
            i += 1

This is creating an endless loop... What stupid detail a开发者_如何学运维m I missing?


If you want to look for 10 active users, you're going to need to be a bit more clever.

for user in itertools.islice((x for x in users if x.is_active), 10):
  # do something


Actually, it's not endless, it just runs through all users 10 times.

If you want the first 10 users (regardless if they're active or not):

while i < 10:
    user = users[i]
    if user.is_active:
        # do something
    i += 1

If you want the first 10 active users:

for user in users:
    if user.is_active:
        #do something
        i += 1
    if i >= 10:
        break


The while-loops condition is not evaluated until you've passed through all the users. You could remove the while and put an if i >= 10: break at the end of the for loop instead.


Try to follow your code on paper and see what it does. You'll notice that you're not grabbing the first ten users, but you are iterating over all the users ten times. The for-loop iterates over all user in users, and the while-loop repeats the for-loop ten times.


It seems like your code would be equivalent to

users = User.objects.filter(is_active=True)[:10]
for user in users:
    #do something

providing you have ten users.


Mabybe your i is never reaching 10. Maybe not even 10 of your users active.

Maybe i > 10 and the condition wasn't checked before that happens.

filter(lambda u:u.is_active, users)[:10]


Using list comprehension:

[user for user in User.objects.all() if user.is_active][:10]

And in case you need to perform any action on such users you can use again list comprehension:

[action(usr) for usr in [user for user in User.objects.all() if user.is_active][:10]]

Or map:

map(action, [user for user in User.objects.all() if user.is_active][:10])


Except for using special iterators (sometimes you import tens of lines of code to write your in a single one, you can call it being clever ^^, while you could do the same with 5 lines and no imports) I think this is the typical case to use break in a for loop

users = User.objects.all()
i = 0
for user in users:
    if user.is_active:
        #do something
        i += 1
    if i == 10:
        break
else:
    #do something if less than 10 active users (if necessary)
0

精彩评论

暂无评论...
验证码 换一张
取 消