我正在使用Python中的Duck Typ。

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 Engine中的DB对象):

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() 方法摘要,以便我可以为所有需要孩子提供实施的对象拥有相同的父班类吗?

也许更重要的是,这是“ Pythonic”吗?我应该走这条路线,还是应该依靠鸭子打字?我的背景是在Java,我正在尝试学习Python做事的方式。

谢谢!

有帮助吗?

解决方案

由于您没有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 方法。

关于这是否是“ Pythonic”的辩论是分裂的。 PEP 3119, 描述了标准,列出了一些利弊(但显然有利于ABC)。它使它进入了标准库,这是一个很好的迹象,许多人认为在某些情况下它有用。就您而言,我认为这是合适的。

如果要确保实现清理方法,则可以用 @abc.virtualmethod 装饰师。这将导致任何尚未覆盖虚拟方法的对象实例化的错误。这也要求您做 abc.ABCMeta 你的班级 __metaclass__.

看到 ABC模块 有关更多信息和一些示例。

这不是通常的事情:通常,只有文档就必须覆盖实施者必须覆盖给定方法的效果。但是,这可能更多是由于 abc 模块(python 2.6中的新模块)比这种方法的感知的不体现性。

为什么不拥有 cleanup 方法只是提出一个 NotImplementedError 什么时候叫?如果他们希望您的孩子课上工作,则必须进行某种实施。

尽管我从未亲自使用过它,但我已经看到了很多参考 ZOPE接口. 。这可能是您任务的过度杀伤,但可能会给您一些方向。对于具有Java背景的人来说,它可能会感到舒适。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top