Vladislav Ladenkov Vladislav Ladenkov - 2 months ago 4
Python Question

Different functions return the same item from a Python dictionary

import json, os

def load_data(filepath):
if not os.path.exists(filepath):
return None
with open(filepath, 'r') as file:
return json.load(file)

def get_biggest_bar(data):
bars = []
for bar in data:
bars.append((bar['Cells']['SeatsCount'] , bar['Number']))
max_number = max(bars)[1]
(item for item in data if item['Number'] == max_number).__next__()
return item, max_number

def get_smallest_bar(data):
bars = []
for bar in data:
bars.append((bar['Cells']['SeatsCount'] , bar['Number']))
min_number = min(bars)[1]
(item for item in data if item['Number'] == min_number).__next__()
return item, min_number

def get_closest_bar(data, longitude, latitude):
coordinates = []
def get_distance(point, input_point):
return ((longitude-input_point[0])**2 + (latitude - input_point[1])**2)**1/2
for cell in data:
coordinates.append([cell['Cells']['geoData']['coordinates'],cell['Number']])
for coor in coordinates:
coor[0] = get_distance(point, coor[0])
closest_bar = min(coordinates)[1]
(item for item in data if item['Number'] == closest_bar).__next__()
return item, closest_bar

if __name__ == '__main__':
data = load_data("Bars.json")
print(get_smallest_bar(data))
print(get_biggest_bar(data))
print(get_closest_bar(data, 50.0, 50.0))


And it's output is:

(dict_values(['Семёновский переулок, дом 21', 'нет', 'район Соколиная Гора', 'Восточный административный округ', 'да', 177, {'type': 'Point', 'coordinates': [37.717115000077776, 55.78262800012168]}, 'СПБ', 272459722, [{'PublicPhone': '(916) 223-32-98'}], 'SПБ']), 37)
(dict_values(['Семёновский переулок, дом 21', 'нет', 'район Соколиная Гора', 'Восточный административный округ', 'да', 177, {'type': 'Point', 'coordinates': [37.717115000077776, 55.78262800012168]}, 'СПБ', 272459722, [{'PublicPhone': '(916) 223-32-98'}], 'SПБ']), 434)
(dict_values(['Семёновский переулок, дом 21', 'нет', 'район Соколиная Гора', 'Восточный административный округ', 'да', 177, {'type': 'Point', 'coordinates': [37.717115000077776, 55.78262800012168]}, 'СПБ', 272459722, [{'PublicPhone': '(916) 223-32-98'}], 'SПБ']), 170)


As you see, items are COMPLETLY identical, but they are diffrent(I tried to devide functions and run them seperatly, and they output diffrent items)! Also, you can see the second number in the fucntion's returns - they are diffrent! Whats the matter?!

Answer

You are using a generator to get item, but on the next line that variable is not what you think it is. Item from inside the generator is out of scope. I would prefer to return the actual generated value. Also, you are getting the closest bar to some point, but not the one you passed into the function.

Thus I think item and point are both global variables that you are using by mistake inside your functions.

I have python2.7, so the syntax to get the next value from the generator may be slightly different.

def load_data(filepath):
    data = [
        {'Number': 10, 'Cells': {'SeatsCount': 10, 'geoData': {'coordinates': (10, 10)}}},
        {'Number': 50, 'Cells': {'SeatsCount': 50, 'geoData': {'coordinates': (50, 50)}}},
        {'Number': 90, 'Cells': {'SeatsCount': 90, 'geoData': {'coordinates': (90, 90)}}}
    ]
    return data

def get_biggest_bar(data):
    bars = []
    for bar in data:
        bars.append((bar['Cells']['SeatsCount'] , bar['Number']))
    max_number = max(bars)[1]
    g = (item for item in data if item['Number'] == max_number)
    return next(g), max_number

def get_smallest_bar(data):
    bars = []
    for bar in data:
        bars.append((bar['Cells']['SeatsCount'] , bar['Number']))
    min_number = min(bars)[1]
    g = (item for item in data if item['Number'] == min_number)
    return next(g), min_number

def get_closest_bar(data, longitude, latitude):
    point = (longitude, latitude)
    coordinates = []
    def get_distance(point, input_point):
        return ((longitude-input_point[0])**2 + (latitude - input_point[1])**2)**1/2
    for cell in data:
        coordinates.append([cell['Cells']['geoData']['coordinates'],cell['Number']])
    for coor in coordinates:
        coor[0] = get_distance(point, coor[0])
    closest_bar = min(coordinates)[1]
    g = (item for item in data if item['Number'] == closest_bar)
    return next(g), closest_bar

if __name__ == '__main__':
    data = load_data("Bars.json")
    print("smallest", get_smallest_bar(data))
    print("biggest", get_biggest_bar(data))
    print("closest", get_closest_bar(data, 50.0, 50.0))

Output:

('smallest', ({'Cells': {'geoData': {'coordinates': (10, 10)}, 'SeatsCount': 10}, 'Number': 10}, 10))
('biggest', ({'Cells': {'geoData': {'coordinates': (90, 90)}, 'SeatsCount': 90}, 'Number': 90}, 90))
('closest', ({'Cells': {'geoData': {'coordinates': (50, 50)}, 'SeatsCount': 50}, 'Number': 50}, 50))