对类的评估返回假

时间:2018-10-01 16:51:00

标签: python class shapely

我写了这个课:

class DSMCalc(object):
    def __init__(self, footprint):
        if footprint.__class__.__base__.__module__ is not 'shapely.geometry.base':
            raise TypeError('footprint input geometry is not a shapely geometry based object')
        self.footprint = footprint

据我所知,我需要做__class__.__base__.__module__的全部业务,因为我试图将所有形状好的对象(例如shapely.geometry.polygon.Polygonshapely.geometry.multipolygon.MultiPolygon)包括在内,并且我发现这种属性组合似乎可行,因为我要包括的所有对象都输出shapely.geometry.base

但是,当我运行代码时,即使放入有效的shapely.geometry.polygon.Polygon对象,我也会遇到TypeError。我已经尝试使用shapely.geometry.base作为字符串和模块使用以上代码。怎么会这样?

一些示例对象会重现该错误:

valid_geojson_polygon_feature = {
'properties': {"name":"test"},
'type': 'Feature',
'geometry': {
    'coordinates': [[(-122.4103173469268, 37.78337247419125), (-122.41042064203376, 37.7833590750075),
                     (-122.41046641056752, 37.78360478527359), (-122.41047393562782, 37.783644775039576),
                     (-122.4103759761863, 37.78365638609612), (-122.4103173469268, 37.78337247419125)]],
    'type': 'Polygon'}}

from shapely.geometry import shape as get_shape
valid_shapely_polygon_feature = get_shape(valid_geojson_polygon_feature['geometry'])
print(valid_shapely_polygon_feature.__class__.__base__.__module__)
DSMCalc(valid_shapely_polygon_feature)

1 个答案:

答案 0 :(得分:5)

您不能依靠is处理字符串文字。即使有效,它也是CPython的实现细节,在这种情况下,即使CPython的实现也不支持它,因为CPython只会自动插入适合标识符(即变量名)规则的字符串文字。您的字符串包含.,这意味着它不会自动被阻止。您可以在交互式提示下轻松看到这一点:

>>> x = 'shapely.geometry.base'  # Not a legal variable name
>>> y = 'shapely.geometry.base'
>>> x is y
False
>>> x = 'abc123'  # Legal variable name
>>> y = 'abc123'
>>> x is y
True

基本上,将测试更改为!= 'shapely.geometry.base',如果需要更多详细信息,请继续阅读the difference between is and ==

我会注意到您的测试在其他方面存在缺陷。现在,您需要在shapely.geometry.base中定义直接父级。但是,如果您将有效的类作为子类,则该子类将无效(因为__base__将引用其他模块的子类,而不是shapely.geometry.base中的最终基类)。更好的解决方案是根据已知的良好基类进行适当的isinstance检查,例如:

# Top of file
from shapely.geometry.base import BaseGeometry, GeometrySequence

# Test code (passing a tuple of legal bases classes is allowed)
if not isinstance(footprint, (BaseGeometry, GeometrySequence)):
    raise TypeError('footprint input geometry is not a shapely geometry based object')

,除了更明确地说明您想要的内容(明确列举合法的基类),并允许所涉及类的间接子类,而不是仅允许该模块中少数基类的直接子类之外,还避免了虚假的情况像CAP_STYLEJOIN_STYLE这样的类型(虽然在shapely.geometry.base中定义,但似乎主要以类似于枚举的常量类存在,而不是与几何相关的实际事物存在,并且可能不是您所键入的类型要允许)。