Вопрос

Я использую уток, печатая в Python.

def flagItem(object_to_flag, account_flagging, flag_type, is_flagged):
    if flag_type == Flags.OFFENSIVE:
        object_to_flag.is_offensive=is_flagged
    elif flag_type == Flags.SPAM:
        object_to_flag.is_spam=is_flagged
    object_to_flag.is_active=(not is_flagged)
    object_to_flag.cleanup()
    return object_to_flag.put()

Где разные объекты передаются как object_to_flag, все из которых имеют is_active, is_spam, is_offensive атрибуты. Они также имеют cleanup() метод.

Объекты, которые я прохожую во всех, имеют тот же базовый класс (они объекты БД в приложении Google App):

class User(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

class Post(db.Model):
    ...
    is_active = db.BooleanProperty(default = True)
    is_spam = db.BooleanProperty(default=False)
    is_offensive = db.BooleanProperty(default=False)
    def cleanup():
        pass

Как я могу сделать cleanup() Метод абстрактна, чтобы у меня был тот же родительский класс для всех этих объектов, которые требуют, чтобы дети предоставляли реализацию?

Возможно, более важно, это «питон»? Должен ли я пойти на этот маршрут, или я должен просто полагаться на печати утки? Мой фон в Яве, и я пытаюсь выучить питон способ делать вещи.

Спасибо!

Это было полезно?

Решение

Поскольку у вас нет ABC доступен, вы можете сделать это с помощью простого метакласса

class Abstract(type(db.Model)):
    def __new__(metacls, clsname, bases, clsdict):
        for methodname in clsdict.pop('_abstract_methods_', []):
            try:
                if not callable(clsdict[methodname]):
                    raise TypeError("{0} must implement {1}".format(clcname, methodname))
            except KeyError:
                raise TypeError("{0} must implement {1}".format(clcname, methodname))
       return super(Abstract, metacls).__new__(metacls, clsname, bases, clsdict)


class RequireCleanup(db.Model):
    __metaclass__ = Abstract
    _abstract_methods_ = ['cleanup']

    def cleanup(self):
        pass

выражение type(db.Model) разрешит к любому метакласму для db.Model Поэтому мы не наступаем в код Google. Кроме того, мы поп _abstract_methods_ из словаря класса до того, как он будет передан в Google __new__ Метод, чтобы мы ничего не нарушали. Если db.Model Уже есть атрибут с этим именем, то вам нужно будет изменить его на что-то еще.

Другие советы

Использовать abc модуль. Отказ В частности, установите метакласс вашего базового класса в ABCMeta и использовать @abstractmethod Декоратор на вашем cleanup метод.

Дискуссия о том, является ли это «питон», разделен. PEP 3119., который описывает стандарт, перечисляет некоторые из плюсов и минусов (но, очевидно, благоприятствуют ABCS). Это сделало его в стандартной библиотеке, что является довольно хорошим показателем того, что многие люди считают это полезным в некоторых обстоятельствах. В вашем случае, я думаю, это уместно.

Если вы хотите убедиться, что метод очистки реализован, вы можете обернуть с помощью @abc.virtualmethod декоратор. Это приведет к появлению ошибки любого объекта, который не переопределил VirtualMethod. Это также требует, чтобы вы делали abc.ABCMeta Ваш класс __metaclass__.

Увидеть ABC модуль Для получения дополнительной информации и некоторых примеров.

Это обычно не сделано: обычно будут просто документы о том, что исполнители должны переопределять данный метод. Однако это может быть больше из-за новинки abc Модуль (новый в Python 2.6), чем воспринимаемая неразборчивость этого подхода.

Почему бы не иметь cleanup Метод просто поднять NotImplementedError Когда это называется? Если они хотят, чтобы ваши детские классы на работе им придется поставить какую-то реализацию на месте.

Хотя я никогда не использовал его лично, я видел много ссылок на Zope Interfaces. Отказ Это может быть дополнительный для вашей задачи, но это может дать вам некоторое направление. И это может чувствовать себя комфортно для кого-то с фоном Java.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top