Mam bardzo prosty ruton python, który polega na przechodzenie przez listę z około 20 000 współrzędnych szerokości i długości geograficznej i obliczanie odległości każdego punktu do punktu odniesienia.deepcopy i python - wskazówki, których należy unikać?
def compute_nearest_points(lat, lon, nPoints=5):
"""Find the nearest N points, given the input coordinates."""
points = session.query(PointIndex).all()
oldNearest = []
newNearest = []
for n in xrange(nPoints):
oldNearest.append(PointDistance(None,None,None,99999.0,99999.0))
newNearest.append(obj2)
#This is almost certainly an inappropriate use of deepcopy
# but how SHOULD I be doing this?!?!
for point in points:
distance = compute_spherical_law_of_cosines(lat, lon, point.avg_lat, point.avg_lon)
k = 0
for p in oldNearest:
if distance < p.distance:
newNearest[k] = PointDistance(
point.point, point.kana, point.english, point.avg_lat, point.avg_lon, distance=distance
)
break
else:
newNearest[k] = deepcopy(oldNearest[k])
k += 1
for j in range(k,nPoints-1):
newNearest[j+1] = deepcopy(oldNearest[j])
oldNearest = deepcopy(newNearest)
#We're done, now print the result
for point in oldNearest:
print point.station, point.english, point.distance
return
początkowo napisałem to w C, stosując dokładnie takie samo podejście, i to działa dobrze tam, i jest w zasadzie chwilowego dla nPoints < = 100. Więc postanowiłem przenieść go do Pythona, ponieważ chciałem użyć SqlAlchemy do robienia innych rzeczy.
Najpierw przeportowałem go bez instrukcji deepcopy, które teraz pieprzą metodę, a to spowodowało, że wyniki są "nieparzyste" lub częściowo niepoprawne, ponieważ niektóre punkty zostały po prostu skopiowane jako referencje (chyba? ?) - ale wciąż było prawie tak szybko, jak wersja C.
Teraz z dodanymi poleceniami deepcopy, rutynowe zadanie wykonuje się poprawnie, ale poniosło ono ekstremalną karę wykonania, a teraz zajmuje kilka sekund wykonanie tej samej pracy.
Wydaje się, że to dość powszechna praca, ale najwyraźniej nie robię tego w sposób pytonowy. Jak powinienem to robić, aby nadal uzyskiwać poprawne wyniki, ale nie muszę wszędzie wprowadzać deepcopy?
EDIT:
mam trafić na znacznie prostsze i szybsze rozwiązanie,
def compute_nearest_points2(lat, lon, nPoints=5):
"""Find the nearest N points, given the input coordinates."""
points = session.query(PointIndex).all()
nearest = []
for point in points:
distance = compute_spherical_law_of_cosines(lat, lon, point.avg_lat, point.avg_lon)
nearest.append(
PointDistance(
point.point, point.kana, point.english, point.avg_lat, point.avg_lon, distance=distance
)
)
nearest_points = sorted(nearest, key=lambda point: point.distance)[:nPoints]
for item in nearest_points:
print item.point, item.english, item.distance
return
Więc w zasadzie jestem tylko co kompletną kopię wejścia i dodanie nowej wartości - odległość od Punkt odniesienia. Następnie stosuję "posortowane" do wynikowej listy, określając, że klucz sortowania powinien być właściwością odległości obiektu PointDistance.
Jest to znacznie szybsze niż zastosowanie deepcopy, chociaż przyznaję, że tak naprawdę nie rozumiem dlaczego. Sądzę, że to zależy od wydajnych implementacji C "posortowanych" Pythona?
Jak wygląda klasa 'PointDistance'? Jeśli uczynisz klasę "PointDistance" prostą, która odnosi się tylko do oryginalnego punktu i jego odległości (tj. Jest to praktycznie krotka z dwoma elementami), nie powinieneś używać 'deepcopy', ponieważ punkty nie ulegną zmianie podczas algorytmu i odległość jest liczbą prostą. –
@ Tamás tak jest w zasadzie tylko słownikiem. jednak w pierwszym przykładzie to zdecydowanie nie działa poprawnie bez deepcopy. może to by działało, gdybym po prostu całkowicie wyeliminował klasę i zamiast tego użył słownika? szczerze mówiąc po prostu nie mam wystarczająco jasnego zrozumienia modelu referencyjnego, aby wiedzieć, co stanie się w tych przypadkach. może mógłbyś rozwinąć lub wskazać mi jakieś inne zasoby lub posty na ten temat? – si28719e