0

I have a piece of code that uses the google maps API to fetch the distance between given locations. So, for example Tour('New+York+NY', 'Lansing+MI','Sacramento+CA') will calculate the locations between NY & Lansing, then Lansing & Sacramento & give the final distance value.

I want to use the add method to be able to specify another tour, for example Tour(Oakland+CA) to create a new route like Tour('New+York+NY', 'Lansing+MI','Sacramento+CA', Oakland+CA), which will then get passed to the class Tour to calculate the new distance with the new destination.

My code is below, however when I pass the values back after the add function, I am given distance of 0. I know that Tour('New+York+NY', 'Lansing+MI','Sacramento+CA', Oakland+CA) works on it's own if passed straight away, but cannot get it to work with add; I realize I might have done something wrong with str or repr, I don't understand those very well yet. Any help would be much appreciated, been trying to solve this for a few hours now.

import requests
import json

class Tour:

def __init__ (self, *args):

    self.args = args


def __str__ (self):

    # returns New+York+NY;Lansing+MI;Los+Angeles+CA
    return ' '.join(self.args)

def __repr__ (self):

    # returns New+York+NY;Lansing+MI;Los+Angeles+CA
    return ' '.join(self.args)

def distance (self, mode = 'driving'):

    self.mode = mode

    meters_list = []

    # counts through the amount of assigned arguments, 'Lansing+MI', 'Los+Angeles+CA' will give 2 
    for i in range(len(self.args)-1):
        #print (self.args[i])


        url = 'http://maps.googleapis.com/maps/api/distancematrix/json?origins=%s&destinations=%s&mode=%s&sensor=false' % (self.args[i], self.args[i+1], self.mode)

        response = requests.get(url)

        # converts json data into a python dictionary
        jsonAsPython = json.loads(response.text)

        # gets the dictionary value for the metres amount by using the relevent keys
        meters = int(jsonAsPython['rows'][0]['elements'][0]['distance']['value'])
        #print (meters)

        meters_list.append(meters)

    return (sum(meters_list))



def __add__ (self, other):

    new_route = str(','.join(self.args + other.args))
    return Tour(new_route)

a = Tour('New+York+NY', 'Lansing+MI','Sacramento+CA')
b = Tour('Oakland+CA')
print (a)
print (b)
print (a.distance())
c = a + b
print(c)
print (c.distance())

Just in case here is also the link to the original project: http://www.cse.msu.edu/~cse231/PracticeOfComputingUsingPython/08_ClassDesign/GoogleMap/Project11.pdf

1 Answers1

0

Your current Tour.__add__ function does something like this:

Tour('a') + Tour('b') -> Tour('a, b')

You want Tour.__add__ to behave like this:

Tour('a') + Tour('b') -> Tour('a', 'b')

You used the splat operator to allow Tour.__init__ to accept an arbitrary number of arguments, so you will have to do the opposite in Tour.__add__. Here's an example for how to do that:

def f(a, b, c):
    print(a, b, c)

f([1, 2, 3])   # TypeError: f() missing 2 required positional arguments: 'b' and 'c'

f(*[1, 2, 3])  # prints 1, 2, 3
f(1, 2, 3)     # prints 1, 2, 3
Blender
  • 289,723
  • 53
  • 439
  • 496
  • Thank you so much, it worked with return Tour(*self.args, *other.args); super helpful! One more question that I had - can you please let me know whether I am using __str__ and __repr__ correctly in this example? From what I understand __repr__ isn't really needed and I can just use one of them, but __str__ is more user facing? Thank you again for all the help! – Philipp Vengrinovich Jan 19 '18 at 06:08
  • @PhilippVengrinovich: this explains it better than I could in a few sentences: https://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python – Blender Jan 19 '18 at 19:31