Totumus Maximus
Totumus Maximus

Reputation: 7573

Python random.sample not working properly?

I'm a complete nab with python. But now I need a simple storage containing MyObject-objects for some project. Each object contains a few StringProperties nothing fancy.

Now I want to get from my list of MyObjects, 10 random objects and store them in some other array.

So I went searching and found random.sample and started implemending it.

def get10RandomMyObjects():
    # waarders maken
    dict = {}
    myObjectsList = []

    # Lijst vullen
    myObjects = MyObject.all()

    randomMyObjects = random.sample(myObjects, 10)

    for o in randomMyObjects:
        dict_myObject = { }
        #some random property setting
        myObjectsList.append(dict_myObject)

    dict['myObjects'] = myObjectsList
    return dict

This is the error I get back:

 File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/random.py", line 314, in sample
    n = len(population)
TypeError: object of type 'Query' has no len()

So obviously something is wrong with the random.sample but my noobness can't decypher what it is. Anyone care to explain me why I can't obtain those 10 random MyObjects I so desire?

Upvotes: 1

Views: 2670

Answers (4)

James Youngman
James Youngman

Reputation: 3733

Looks like the Query object is a generator. random.sample likes to know how many items there are in order to create the sample. So the simplest thing to do is put the items to be sampled in a list:

randomMyObjects = random.sample(list(myObjects), 10)

Upvotes: 2

Eser Aygün
Eser Aygün

Reputation: 8004

random.sample() works on lists. Obviously, MyObject.all() does not return a list but a Query object. If Query is at least iterable then you can write:

myObjects = list(MyObject.all())

Otherwise, you have to create a list from MyObject.all() manually.

Upvotes: 2

Gaslight Deceive Subvert
Gaslight Deceive Subvert

Reputation: 20354

You may also use:

randomMyObjects = MyObject.all().order_by('?')[:10]

Which is faster because it will let the database do the random ordering and only load the 10 first objects into memory.

Upvotes: 1

brice
brice

Reputation: 25039

There is nothing wrong with random.sample(). What is happening is that myObjects is not a collection.

Most likely, myObjects is an iterator. You'll have to turn it into a list before using it in random.sample():

randomMyObjects = random.sample(list(myObjects),10)

Upvotes: 1

Related Questions