Оценка класса возвращает false - PullRequest
0 голосов
/ 01 октября 2018

Я написал этот класс:

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.

Однако, когда я запускаю кодЯ получаю TypeError даже при вводе действительного shapely.geometry.polygon.Polygon объекта.Я пробовал приведенный выше код с 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 голосов
/ 01 октября 2018

Нельзя полагаться на is, работающую со строковыми литералами.Даже когда это работает, это деталь реализации CPython, и в этом случае, даже реализация CPython не поддерживает его, потому что CPython только автоматически интернирует строковые литералы, которые соответствуют правилам для идентификаторов (то есть имен переменных).Ваша строка содержит . s, что означает, что она не автоматически интернируется.Вы можете легко увидеть это в интерактивном режиме:

>>> 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', и, если вам нужна дополнительная информация, прочитайте разницу между is и ==.

Замечу, что ваш тест некорректен в других отношениях.Прямо сейчас вам требуется, чтобы непосредственный родитель был определен в 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_STYLE и JOIN_STYLE (которые, хотя и определены в shapely.geometry.base, по-видимому, существуют в основном в виде простого перечисления-подобные классы констант, а не фактические вещи, связанные с геометрией, и, вероятно, не те типы, которые вы бы хотели разрешить).

...