On a website, I am trying to sort a list of shop by their relative position of the user. Let me explain.
A shop looks something like this:
class Shop(models.Model):
latitude = models.DecimalField(max_digits=9, decimal_places=6)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
I get the position of the user in the session.
request.session['user_latitude']
request.session['user_longitude']
So now I got a list of shop and I want to sort them. So I tried this:
def distance_of_the_shop(shop):
# compute the distance between the shop and the user and return it
return computed_distance
sorted(shop_list, key=distance_of_the_shop)
The question is pretty simple, how to pass more than one argument to the method distance_of_the_shop
?
**kwargs: Pass multiple arguments to a function in Python If so, use **kwargs . **kwargs allow you to pass multiple arguments to a function using a dictionary. In the example below, passing **{'a':1, 'b':2} to the function is similar to passing a=1, b=1 to the function.
The * symbol is used to pass a variable number of arguments to a function. Typically, this syntax is used to avoid the code failing when we don't know how many arguments will be sent to the function.
Every function in Python receives a predefined number of arguments, if declared normally, like this: def myfunction(first, second, third): # do something with the 3 variables ... The "bar" function receives 3 arguments.
Just wrap the call in a lambda:
ulong, ulat = request.session['user_latitude'], request.session['user_longitude']
sorted(shop_list, key=lambda shop: distance_of_the_shop(shop, ulong, ulat))
and add two more arguments to the distance_of_the_shop()
function to receive the longitude and latitude.
The sorted()
function calls the key
for each value in shop_list
, but nothing says the callable cannot itself call other functions. A lambda
is the easiest way to create a new wrapper function that does just that.
You could also use a functools.partial()
object, provided the longitude and latitude values can be passed in as keyword arguments, or accepts those two values as the first two positional arguments. Treating them as keyword arguments is probably best, even if they are given a position (no default value), you can use their names as keyword arguments in the partial()
.
Assuming the definition is:
def distance_of_the_shop(shop, long, lat):
# ...
then use
sorted(shop_list, key=partial(distance_of_the_shop, long=ulong, lat=ulat))
and sorted()
will pass each shop
to the partial()
, which in turn calls distance_of_the_shop(shop, long=ulong, lat=ulat)
Your question is hard to comprehend because you never define a distance
function, and the function you do provide, distance_of_the_shop
, actually takes a single argument.
If I understand correctly, you would like distance_of_the_shop
to receive the current user and the shop being compared. To achieve that, use a lambda
:
shop_list.sort(key=lambda shop: distance_of_the_shop(user, shop))
Also note that it doesn't make sense to call sorted
without assigning its value to some variable or container. If you want to sort a list in-place, use its sort
method, as shown above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With