我使用Python和Sqlalchemy在Sqlite数据库中存储纬度和经度值。我已经为我的Location对象创建了一个hybrid method,
@hybrid_method
def great_circle_distance(self, other):
"""
Tries to calculate the great circle distance between the two locations
If it succeeds, it will return the great-circle distance
multiplied by 3959, which calculates the distance in miles.
If it cannot, it will return None.
"""
return math.acos( self.cos_rad_lat
* other.cos_rad_lat
* math.cos(self.rad_lng - other.rad_lng)
+ self.sin_rad_lat
* other.sin_rad_lat
) * 3959所有像cos_rad_lat和sin_rad_lat这样的值都是我为优化计算而预先计算的值。无论如何,当我运行以下查询时,
pq = Session.query(model.Location).filter(model.Location.great_circle_distance(loc) < 10)我得到以下错误,
line 809, in great_circle_distance
* math.cos(self.rad_lng - other.rad_lng)
TypeError: a float is required例如,当我打印self.rad_lng和other.rad_lng的值时,
self.rad_lng: Location.rad_lng
other.rad_lng: -1.29154947064我做错了什么?
发布于 2011-09-29 23:37:58
您不能真正以这种方式使用math模块:
>>> c = toyschema.Contact()
>>> c.lat = 10
>>> c.lat
10
>>> import math
>>> math.cos(c.lat)
-0.83907152907645244
>>> math.cos(toyschema.Contact.lat)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a float is required您将在@great_circle_distance.expression method中组合sqalchemy.func.*而不是math.*,以实现所有这类智能。不幸的是,使用sqlite也不能做到这一点;你可以使用PostgreSQL来doesn't provide trig functions,或者你可以尝试add these functions to sqlite yourself:
编辑向sqlite添加函数实际上并不难:这是未经测试的。
我必须将数学函数添加到sqlite:
engine = sqlalchemy.create_engine("sqlite:///:memory:/")
raw_con = engine.raw_connection()
raw_con.create_function("cos", 1, math.cos)
raw_con.create_function("acos", 1, math.acos)
class Location(...):
...
@hybrid_method
def great_circle_distance(self, other):
"""
Tries to calculate the great circle distance between
the two locations by using the Haversine formula.
If it succeeds, it will return the Haversine formula
multiplied by 3959, which calculates the distance in miles.
If it cannot, it will return None.
"""
return math.acos( self.cos_rad_lat
* other.cos_rad_lat
* math.cos(self.rad_lng - other.rad_lng)
+ self.sin_rad_lat
* other.sin_rad_lat
) * 3959
@great_circle_distance.expression
def great_circle_distance(cls, other):
return sqlalchemy.func.acos( cls.cos_rad_lat
* other.cos_rad_lat
* sqlalchemy.func.cos(cls.rad_lng - other.rad_lng)
+ cls.sin_rad_lat
* other.sin_rad_lat
) * 3959发布于 2011-09-29 18:23:13
显然,你不能从这个字符串中得到一个浮点数。
这是因为您使用的是"self",作为调用的第一个参数,它表明该方法是对象的一部分,而不是您可能传递的某个变量。
你应该试试这个:
def great_circle_distance(self, first, other):
"""
Tries to calculate the great circle distance between
the two locations by using the Haversine formula.
If it succeeds, it will return the Haversine formula
multiplied by 3959, which calculates the distance in miles.
If it cannot, it will return None.
"""
return math.acos( self.cos_rad_lat
* other.cos_rad_lat
* math.cos(first.rad_lng - other.rad_lng)
+ self.sin_rad_lat
* other.sin_rad_lat
) * 3959我假设上面的全局变量"self.cos_rad_lat“和"self.sin_rad_lat”是在程序中的其他地方用正确的值初始化的,可能是在同一对象的"init“部分。
发布于 2011-09-29 18:29:22
看起来你做的每件事都是正确的,但不知何故,这个方法并没有真正“混合”起来。你会不会做了一些愚蠢的事情,比如在你的源代码中没有真正的放置装饰器?
https://stackoverflow.com/questions/7595050
复制相似问题